mirror of
https://github.com/wahyd4/links.git
synced 2026-08-08 21:04:53 +10:00
Update code to create posts
This commit is contained in:
Binary file not shown.
@@ -7,8 +7,6 @@ from . import api_views
|
||||
# Create a router and register our viewsets with it
|
||||
router = DefaultRouter(trailing_slash=False)
|
||||
router.register('pages', page_views.PageViewSet, basename='api-pages')
|
||||
# for API compatibility
|
||||
router.register('newsletters', post_views.PostViewSet, basename='api-newsletters')
|
||||
router.register('posts', post_views.PostViewSet, basename='api-posts')
|
||||
router.register('music', api_views.MusicViewSet, basename='api-music')
|
||||
|
||||
|
||||
+38
-2
@@ -10,16 +10,52 @@ class PageSerializer(serializers.ModelSerializer):
|
||||
'created_at', 'updated_at']
|
||||
|
||||
class PostSerializer(serializers.ModelSerializer):
|
||||
tags = serializers.PrimaryKeyRelatedField(many=True, queryset=Tag.objects.all(), required=False)
|
||||
tags = serializers.ListField(child=serializers.CharField(), required=False, write_only=True, help_text="List of tag slugs")
|
||||
tag_details = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
fields = ['id', 'title', 'content', 'tags', 'created_at', 'updated_at']
|
||||
fields = ['id', 'title', 'content', 'tags', 'tag_details', 'created_at', 'updated_at']
|
||||
read_only_fields = ['id', 'created_at', 'updated_at']
|
||||
extra_kwargs = {
|
||||
'title': {'required': True},
|
||||
'content': {'required': True}
|
||||
}
|
||||
|
||||
def get_tag_details(self, obj):
|
||||
return [{'id': tag.id, 'name': tag.name, 'slug': tag.slug} for tag in obj.tags.all()]
|
||||
|
||||
def create(self, validated_data):
|
||||
tag_slugs = validated_data.pop('tags', [])
|
||||
post = Post.objects.create(**validated_data)
|
||||
|
||||
for tag_slug in tag_slugs:
|
||||
try:
|
||||
tag = Tag.objects.get(slug=tag_slug)
|
||||
except Tag.DoesNotExist:
|
||||
# If tag doesn't exist, create it with the slug as both name and slug
|
||||
tag = Tag.objects.create(name=tag_slug, slug=tag_slug)
|
||||
post.tags.add(tag)
|
||||
|
||||
return post
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
tag_slugs = validated_data.pop('tags', None)
|
||||
for attr, value in validated_data.items():
|
||||
setattr(instance, attr, value)
|
||||
|
||||
if tag_slugs is not None:
|
||||
instance.tags.clear()
|
||||
for tag_slug in tag_slugs:
|
||||
try:
|
||||
tag = Tag.objects.get(slug=tag_slug)
|
||||
except Tag.DoesNotExist:
|
||||
# If tag doesn't exist, create it with the slug as both name and slug
|
||||
tag = Tag.objects.create(name=tag_slug, slug=tag_slug)
|
||||
instance.tags.add(tag)
|
||||
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
class ImageSerializer(serializers.ModelSerializer):
|
||||
url = serializers.SerializerMethodField()
|
||||
|
||||
-453
@@ -1,453 +0,0 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: GoLinks API
|
||||
description: API documentation for GoLinks service
|
||||
version: 1.0.0
|
||||
|
||||
servers:
|
||||
- url: http://localhost:8000
|
||||
description: Local development server
|
||||
|
||||
paths:
|
||||
/api/pages:
|
||||
get:
|
||||
summary: List all pages
|
||||
description: Retrieve a paginated list of all pages
|
||||
parameters:
|
||||
- in: query
|
||||
name: page
|
||||
schema:
|
||||
type: integer
|
||||
description: Page number for pagination
|
||||
- in: query
|
||||
name: page_size
|
||||
schema:
|
||||
type: integer
|
||||
description: Number of items per page
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PageList'
|
||||
|
||||
post:
|
||||
summary: Create a new page
|
||||
description: Create a new page with the provided data
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PageCreate'
|
||||
responses:
|
||||
'201':
|
||||
description: Page created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Page'
|
||||
|
||||
/api/newsletters:
|
||||
get:
|
||||
summary: List all newsletters
|
||||
description: Retrieve a paginated list of all newsletters
|
||||
parameters:
|
||||
- in: query
|
||||
name: page
|
||||
schema:
|
||||
type: integer
|
||||
description: Page number for pagination
|
||||
- in: query
|
||||
name: page_size
|
||||
schema:
|
||||
type: integer
|
||||
description: Number of items per page
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NewsletterList'
|
||||
|
||||
post:
|
||||
summary: Create a new newsletter
|
||||
description: Create a new newsletter with the provided data
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NewsletterCreate'
|
||||
responses:
|
||||
'201':
|
||||
description: Newsletter created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Newsletter'
|
||||
|
||||
/api/collections:
|
||||
get:
|
||||
summary: List all collections
|
||||
description: Retrieve a paginated list of all image collections
|
||||
parameters:
|
||||
- in: query
|
||||
name: page
|
||||
schema:
|
||||
type: integer
|
||||
description: Page number for pagination
|
||||
- in: query
|
||||
name: page_size
|
||||
schema:
|
||||
type: integer
|
||||
description: Number of items per page
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CollectionList'
|
||||
|
||||
post:
|
||||
summary: Create a new collection
|
||||
description: Create a new image collection
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CollectionCreate'
|
||||
responses:
|
||||
'201':
|
||||
description: Collection created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CollectionResponse'
|
||||
|
||||
/api/collections/{collection_id}:
|
||||
delete:
|
||||
summary: Delete a collection
|
||||
description: Delete a collection and all its images
|
||||
parameters:
|
||||
- in: path
|
||||
name: collection_id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: The ID of the collection to delete
|
||||
responses:
|
||||
'200':
|
||||
description: Collection deleted successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SuccessResponse'
|
||||
|
||||
/api/collections/{collection_id}/upload_images:
|
||||
post:
|
||||
summary: Upload images to a collection
|
||||
description: Upload one or more images to a collection with optional descriptions
|
||||
parameters:
|
||||
- in: path
|
||||
name: collection_id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: The ID of the collection to upload images to
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: binary
|
||||
description: List of image files to upload. Only image/* content types are allowed.
|
||||
descriptions:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Optional list of descriptions for the uploaded images. Each description corresponds to the image at the same index.
|
||||
required:
|
||||
- file
|
||||
responses:
|
||||
'201':
|
||||
description: Images uploaded successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [success]
|
||||
example: success
|
||||
message:
|
||||
type: string
|
||||
example: "Successfully uploaded 2 images"
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Image'
|
||||
'400':
|
||||
description: Bad request - invalid file or upload failed
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [error]
|
||||
example: error
|
||||
message:
|
||||
type: string
|
||||
example: "Invalid file type. Only images are allowed."
|
||||
|
||||
/api/images/{image_id}:
|
||||
delete:
|
||||
summary: Delete an image
|
||||
description: Delete a specific image from a collection
|
||||
parameters:
|
||||
- in: path
|
||||
name: image_id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: The ID of the image to delete
|
||||
responses:
|
||||
'200':
|
||||
description: Image deleted successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SuccessResponse'
|
||||
|
||||
components:
|
||||
schemas:
|
||||
Page:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
url:
|
||||
type: string
|
||||
title:
|
||||
type: string
|
||||
summary:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
updated_at:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
PageCreate:
|
||||
type: object
|
||||
required:
|
||||
- url
|
||||
- title
|
||||
properties:
|
||||
url:
|
||||
type: string
|
||||
title:
|
||||
type: string
|
||||
summary:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
|
||||
PageList:
|
||||
type: object
|
||||
properties:
|
||||
count:
|
||||
type: integer
|
||||
next:
|
||||
type: string
|
||||
nullable: true
|
||||
previous:
|
||||
type: string
|
||||
nullable: true
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Page'
|
||||
|
||||
Newsletter:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
title:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
enum: [technology, world_news]
|
||||
content:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
NewsletterCreate:
|
||||
type: object
|
||||
required:
|
||||
- title
|
||||
- type
|
||||
- content
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
enum: [technology, world_news]
|
||||
content:
|
||||
type: string
|
||||
|
||||
NewsletterList:
|
||||
type: object
|
||||
properties:
|
||||
count:
|
||||
type: integer
|
||||
next:
|
||||
type: string
|
||||
nullable: true
|
||||
previous:
|
||||
type: string
|
||||
nullable: true
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Newsletter'
|
||||
|
||||
Collection:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
name:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
image_count:
|
||||
type: integer
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
CollectionCreate:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
|
||||
CollectionList:
|
||||
type: object
|
||||
properties:
|
||||
count:
|
||||
type: integer
|
||||
next:
|
||||
type: string
|
||||
nullable: true
|
||||
previous:
|
||||
type: string
|
||||
nullable: true
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Collection'
|
||||
|
||||
CollectionResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [success]
|
||||
message:
|
||||
type: string
|
||||
data:
|
||||
$ref: '#/components/schemas/Collection'
|
||||
|
||||
Image:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
collection:
|
||||
type: string
|
||||
format: uuid
|
||||
title:
|
||||
type: string
|
||||
description: The original filename of the uploaded image
|
||||
description:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Optional description for the image
|
||||
file_key:
|
||||
type: string
|
||||
description: Internal storage key for the image
|
||||
content_type:
|
||||
type: string
|
||||
description: MIME type of the image
|
||||
example: "image/jpeg"
|
||||
size:
|
||||
type: integer
|
||||
description: Size of the image in bytes
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
updated_at:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
ImageUploadResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [success]
|
||||
message:
|
||||
type: string
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Image'
|
||||
|
||||
SuccessResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [success]
|
||||
message:
|
||||
type: string
|
||||
|
||||
ErrorResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [error]
|
||||
message:
|
||||
type: string
|
||||
+69
-46
@@ -49,10 +49,10 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Page'
|
||||
|
||||
/api/newsletters:
|
||||
/api/posts:
|
||||
get:
|
||||
summary: List all newsletters
|
||||
description: Retrieve a paginated list of all newsletters
|
||||
summary: List all posts
|
||||
description: Retrieve a paginated list of all posts
|
||||
parameters:
|
||||
- in: query
|
||||
name: page
|
||||
@@ -70,24 +70,24 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NewsletterList'
|
||||
$ref: '#/components/schemas/PostList'
|
||||
|
||||
post:
|
||||
summary: Create a new newsletter
|
||||
description: Create a new newsletter with the provided data
|
||||
summary: Create a new post
|
||||
description: Create a new post with the provided data
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NewsletterCreate'
|
||||
$ref: '#/components/schemas/PostCreate'
|
||||
responses:
|
||||
'201':
|
||||
description: Newsletter created successfully
|
||||
description: Post created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Newsletter'
|
||||
$ref: '#/components/schemas/Post'
|
||||
|
||||
/api/collections:
|
||||
get:
|
||||
@@ -151,8 +151,8 @@ paths:
|
||||
|
||||
/api/collections/{collection_id}/upload_images:
|
||||
post:
|
||||
summary: Upload images to collection
|
||||
description: Upload one or multiple images to a collection
|
||||
summary: Upload images to a collection
|
||||
description: Upload one or more images to a collection with optional descriptions
|
||||
parameters:
|
||||
- in: path
|
||||
name: collection_id
|
||||
@@ -160,7 +160,7 @@ paths:
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: The ID of the collection
|
||||
description: The ID of the collection to upload images to
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
@@ -173,13 +173,33 @@ paths:
|
||||
items:
|
||||
type: string
|
||||
format: binary
|
||||
description: List of image files to upload. Only image/* content types are allowed.
|
||||
descriptions:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Optional list of descriptions for the uploaded images. Each description corresponds to the image at the same index.
|
||||
required:
|
||||
- file
|
||||
responses:
|
||||
'201':
|
||||
description: Images uploaded successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ImageUploadResponse'
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [success]
|
||||
example: success
|
||||
message:
|
||||
type: string
|
||||
example: "Successfully uploaded 2 images"
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Image'
|
||||
|
||||
/api/images/{image_id}:
|
||||
delete:
|
||||
@@ -254,38 +274,43 @@ components:
|
||||
items:
|
||||
$ref: '#/components/schemas/Page'
|
||||
|
||||
Newsletter:
|
||||
Post:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
title:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
enum: [technology, world_news]
|
||||
content:
|
||||
type: string
|
||||
tag_details:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Tag'
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
updated_at:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
NewsletterCreate:
|
||||
PostCreate:
|
||||
type: object
|
||||
required:
|
||||
- title
|
||||
- type
|
||||
- content
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
enum: [technology, world_news]
|
||||
content:
|
||||
type: string
|
||||
tags:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: List of tag slugs to associate with the post
|
||||
|
||||
NewsletterList:
|
||||
PostList:
|
||||
type: object
|
||||
properties:
|
||||
count:
|
||||
@@ -299,7 +324,19 @@ components:
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Newsletter'
|
||||
$ref: '#/components/schemas/Post'
|
||||
|
||||
Tag:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
slug:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
|
||||
Collection:
|
||||
type: object
|
||||
@@ -360,30 +397,25 @@ components:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
collection:
|
||||
type: string
|
||||
format: uuid
|
||||
title:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
content_type:
|
||||
type: string
|
||||
size:
|
||||
type: integer
|
||||
url:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
ImageUploadResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
updated_at:
|
||||
type: string
|
||||
enum: [success]
|
||||
message:
|
||||
format: date-time
|
||||
url:
|
||||
type: string
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Image'
|
||||
|
||||
SuccessResponse:
|
||||
type: object
|
||||
@@ -393,12 +425,3 @@ components:
|
||||
enum: [success]
|
||||
message:
|
||||
type: string
|
||||
|
||||
ErrorResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [error]
|
||||
message:
|
||||
type: string
|
||||
|
||||
Reference in New Issue
Block a user