欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > Vue全栈开发旅游网项目(5)-景点详情模块API接口设计

Vue全栈开发旅游网项目(5)-景点详情模块API接口设计

2024/11/5 1:30:36 来源:https://blog.csdn.net/Tttian622/article/details/143434349  浏览:    关键词:Vue全栈开发旅游网项目(5)-景点详情模块API接口设计

1.前言

通过提供 API,开发者可以重用现有的代码和功能,而不需要从头开始编写。

极大提高了开发效率并减少了重复工作。

同时也使得单独修改或替换系统的某个部分变得更加容易,而不会影响到其他部分。

2.创建公共模型

编写公共模型:

from django.db import modelsclass CommonModel(models.Model):#数据模型公共类is_valid = models.BooleanField('是否有效',default=True)created_at = models.DateTimeField('创建时间',auto_now_add=True)updated_at = models.DateTimeField('修改时间',auto_now=True)class Meta:abstract = True #此步必不可少 否则会创建表

2.1 删去重复项

至此,sight/models.py中的

与模型公共类相同的部分代码已再无他用,除之。

2.2 继承:

from utils.models import CommonModel # 继承

2.3 类的变化:

class Sight(models.Model)  --->  class Sight(CommonModel)

3.创建表结构

3.1 生成单独文件夹用于储存表结构信息

python manage.py startapp accounts

3.2 创建表结构

文件地址:accounts/models.py

from django.db import models
from utils.models import CommonModelclass User(CommonModel):# 用户数据模型username = models.CharField("用户名", max_length=32, unique=True)password = models.CharField("密码", max_length=256)nickname = models.CharField("昵称", max_length=32, unique=True)avatar = models.ImageField("头像", null=True, upload_to="avatar/%Y%m")class Meta:db_table = "account_user"

3.2 激活该文件

3.2.1 定义

文件地址:accounts/apps.py

from django.apps import AppConfigclass AccountsConfig(AppConfig):default_auto_field = 'django.db.models.BigAutoField'name = 'accounts'

3.2.2 配置

在 Django 项目的 settings.py 文件中,

通过在 INSTALLED_APPS 中包含这个配置类,你可以确保 Django 在启动时加载这个应用。

INSTALLED_APPS = ['accounts.apps.AccountsConfig'#用户管理
]

通过以上两项操作,Django 会使用 AccountsConfig 类来配置 accounts 应用,

而不是使用默认的配置。 

4. 测试

由于更改了sight中的部分信息用于创建公共模型

所以可测试sight/list界面代码 观察是否可执行 并功能与之前的一致

http://localhost:8000/sight/sight/list/

5.system模块下新建相关数据模型

文件地址:system/models.py  原基础代码可看:2.新建system模块并建立模型

img = models.ImageField('图片',upload_to='%Y%m/file',max_length=256)

图片地址列用于记录图片所在位置

summary = models.CharField('图片说明',max_length=32,null=True, blank=True )

图片说明(描述)列用于记录图片简介、名称等信息

user=models.ForeignKey(User,on_delete=models.SET(None),related_name="upload_image",verbose_name='上传的用户',null=True,blank=True)

用户id(主键)列,参数1【User】:用户数据源可以将用户id传入到该属性中;
参数2【on_delete=models.SET(None)】:级联关系;主键删除后,外键值空
参数3【related_name="upload_image"】:关联名字;
参数4【verbose_name】:提供了外键字段的人类可读名称;
参数5【null/blank=True】:允许为空null

content_type = models.ForeignKey(ContentType,on_delete=models.CASCADE)

类型适配列,如两个表没有配置主外键关系,还需要实现主外键关联查询,

即利用传统的处理方式,构建一张字典表,将主外关系建立起来。

在Django中提供构建主外关系的策略,可使用Django_ContentType实现该字典表功能。

ContentType特征:

每构建一个新数据源,都会在该表中进行注册,用于之后的主外关系,用于Django框架维护。

content_object = GenericForeignKey('content_type','object_id')   

配置主外关联关系,如:向system_image_related表中添加数据时,

需要明确content_id对应Django_content_type表中哪一个id值。

class ImageRelated(CommonModel):#图片资源img = models.ImageField('图片',upload_to='%Y%m/file',max_length=256)summary = models.CharField('图片说明',max_length=32,null=True, blank=True )user = models.ForeignKey(User,on_delete=models.SET(None),related_name="upload_image",verbose_name='上传的用户',null=True,blank=True)content_type = models.ForeignKey(ContentType,on_delete=models.CASCADE)#关联名称标识object_id = models.IntegerField('关联的模型')content_object = GenericForeignKey('content_type','object_id')class Meta:db_table = 'system_image_related'

6.sight模块下新建相关数据模型

6.1 配置关于景点更多图片

GenericRelation用于非主外关系的一对多关联,与GenericForeignKey配合使用    

参数1,关联目标,关联系统模块图片管理数据源;

参数2,标识名/关联对象名;   参数3:关联对象名(查询)

class Sight(CommonModel):""" 景点基础信息 """name = models.CharField('名称', max_length=64)desc = models.CharField('描述', max_length=256)#......images = GenericRelation(ImageRelated,verbose_name='关联的图片',related_query_name='rel_sight_images')class Meta:db_table ='sight'ordering = ['-updated_at']

6.2 配置景点详情数据模型

6.2.1 数据归类

新建文件sight/choices.py

from django.db import models
class TicketTpye(models.IntegerChoices):#门票类型ADULT = 11,'成人票'CHILD = 12,'儿童票'
class TicketStatus(models.IntegerChoices):#门票状态OPEN = 1,'开放购买'CLOSED = 0,'暂未开放'
class EntryWay(models.IntegerChoices):#入园方式BY_TICKET = 0,'短信换票入园'BY_CODE= 1,'凭验证码入园'

6.2.2 景点详情

class Info(models.Model):# 景点详情sight = models.OneToOneField(Sight,on_delete=models.CASCADE)entry_explain = models.CharField('参考说明',max_length=1024,null=True,blank=True)play_way = models.TextField('特色玩法',null=True,blank=True)tips = models.TextField('温馨提示',null=True,blank=True)traffic = models.TextField('交通到达',null=True,blank=True)class Meta:db_table = 'sight_info'

6.2.3 景点门票

class Ticket(CommonModel):#门票sight = models.ForeignKey(Sight, related_name='tickets', verbose_name='景点门票',on_delete=models.PROTECT)name = models.CharField('名称',max_length=128)desc = models.CharField('描述', max_length=64, null=True, blank=True)types = models.SmallIntegerField('类型',choices=TicketTpye.choices,default=TicketTpye.ADULT,help_text="默认为成人票")price = models.FloatField('价格(原价)')discount = models.FloatField('折扣',default=0)total_stock = models.PositiveIntegerField('总库存',default=0)remain_stock = models.PositiveIntegerField('剩余库存', default=0)expire_date = models.IntegerField('有效期', default=1)return_policy = models.CharField('退改政策', max_length=64, default='条件退')has_invoice = models.BooleanField('是否提供发票', default=True)entry_way = models.SmallIntegerField('入园方式',choices=EntryWay.choices,default=EntryWay.BY_TICKET)tips = models.TextField('预定须知', null=True, blank=True)remark = models.TextField('其他说明', null=True, blank=True)status = models.SmallIntegerField('状态',choices=TicketStatus.choices,default=TicketStatus.OPEN)class Meta:db_table = 'sight_ticket'

6.2.4 评论及回复

class Comment(CommonModel):# 评论及回复user = models.ForeignKey(User, verbose_name='评论人',related_name = 'comments',on_delete=models.CASCADE)sight = models.ForeignKey(Sight,verbose_name='景点',related_name = 'comments',on_delete = models.CASCADE)content = models.TextField('评论内容', blank=True, null=True)is_top = models.BooleanField('是否置顶',default = False)love_count = models.IntegerField('点赞次数',default=0)score = models.FloatField('评分',default=5)ip_address = models.CharField('IP地址', blank=True, null=True, max_length=64)is_public = models.SmallIntegerField('是否公开', default=1)reply = models.ForeignKey('self',blank=True,null=True,related_name = 'reply_comment',verbose_name = '回复',on_delete = models.CASCADE)images = GenericRelation(ImageRelated,verbose_name = '关联的图片',related_query_name = "rel_comment_images")class Meta:db_table = 'sight_comment'ordering = ['-love_count','-created_at']

7.设计响应单个对象的类

新建utils/serializers.py

7.1 序列化

class BaseSerializer(object):def __init__(self, obj):self.obj = objdef to_dict(self):return {}

7.2 对元数据进行序列化(分页)

class MetaSerializers(object):def __init__(self, page, page_count, total_count, **kwargs):""":param page: 当前页:param page_count:总页数:param total_count: 总记录数"""self.page = pageself.page_count = page_countself.total_count = total_countdef to_dict(self):return {"current_page":self.page,"page_count":self.page_count,"total_count":self.total_count}

7.3 数据列表页面类(封装)

class BaseListPageSerializer(object):#分页封装类#paginator页面信息def __init__(self, page_obj,paginator=None,object_list=[]):""":param page_obj: 当前页的对象:param paginator: 分页器对象:param object_list: 当前页的数据列表"""self.page_obj = page_objself.paginator = paginator if paginator else page_obj.paginatorself.object_list = object_list if object_list else page_obj.object_listdef get_object(self,obj):#转换成对象,子类重写return {}def to_dict(self):page = self.page_obj.numberpage_count = self.page_obj.paginator.num_pagestotal_count = self.page_obj.paginator.countmeta = MetaSerializers(page=page,page_count=page_count,total_count=total_count).to_dict()objects=[]for obj in self.object_list:objects.append(self.get_object(obj))return {'meta':meta,'objects':objects}

7.4 删除功能重复项

sight/views.pySightListView类中:

8.设计错误回应类

新建utils/response404.py

from django.http import JsonResponse
class NotFoundJsonResponse(JsonResponse):# 400 对应json的响应status_code = 400def __init__(self, *args, **kwargs):data = {"error_code":"404000","error_msg":"您访问的内容不存在或已删除"}super().__init__(data,*args, **kwargs)

9.景点列表接口开发

9.1 设计响应数据结构

新建sight/serializers.py

接受一个 Sight 模型的实例 obj 作为参数,并返回一个字典,该字典包含了要序列化的数据。

from utils.serializers import BaseListPageSerializerclass SightListSerializer(BaseListPageSerializer):def get_object(self, obj):return {'id': obj.id,'name': obj.name,'main_img': obj.main_img.url,'min_price': obj.min_price,'score': obj.score,'province': obj.province,'city': obj.city,'comment_count': 0}

9.2 设计视图函数

将刚刚7.4章节中,sight/views.py删除后的代码补全,并实现了对分页对象的序列化操作。

class SightListView(ListView):paginate_by = 5def get_queryset(self):query = Q(is_valid=True)is_hot = self.request.GET.get('is_hot',None)if is_hot:query = query & Q(is_hot=True)is_top = self.request.GET.get('is_top',None)if is_top:query = query & Q(is_top=True)queryset = Sight.objects.filter(query)return querysetdef render_to_response(self, context, **response_kwargs):page_obj = context['page_obj']👇if page_obj is not None:data = serializers.SightListSerializer(page_obj).to_dict()return http.JsonResponse(data)else:return NotFoundJsonResponse()👆

9.3 构建地址函数

文件地址:sight/urls.py

from django.urls import path
from sight import viewsurlpatterns = [path('sight/list/',views.SightListView.as_view(),name='sight_list')
]

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com