LintCode Django定义模型教程

本练习重点要掌握的地方

1. 根据项目描述,定义数据模型,数据模型的设计有原则,要符合数据库的三范式,要尽可能的解耦。

2. 熟悉表的外键关联

3. ORM框架

4. 根据业务需求,在Django框架中添加索引,以及唯一约束。

5. 借助Django框架编写单元测试,调试定义的模型。

LintCode 2427 实现推文模型

根据描述定义字段,只有三个字段,其中user字段是外键,使用Django框架定义好的,content是text,创建时间是日期类型,使用自动添加模版。

from django.db import models
from django.contrib.auth.models import User

class Tweet(models.Model):
    # write your code here
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    content = models.CharField(max_length=140)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f'{self.created_at} {self.user}: {self.content}'

 让我们来过一遍一下单元测试:

from django.contrib.auth.models import User
from django.test import TestCase
from tweets.models import Tweet
from datetime import date
import re


class TweetTests(TestCase):
    def test_tweet_model_attributes(self):
        self.assertEqual(hasattr(Tweet, 'user'), True)
        self.assertEqual(hasattr(Tweet, 'content'), True)
        self.assertEqual(hasattr(Tweet, 'created_at'), True)

    def test_tweet_model(self):
        user = User.objects.create(username='linghu', password='god')
        tweet = Tweet.objects.create(content='jiuzhangdafahao')

        self.assertEqual(tweet.user, None)
        self.assertEqual(tweet.created_at.day, date.today().day)

        tweet.delete()
        Tweet.objects.create(user=user, content='jiuzhangdafahao')

        user.delete()

        self.assertEqual(Tweet.objects.all().count(), 1)
        self.assertEqual(Tweet.objects.first().user, None)
        self.assertEqual(Tweet.content.field.max_length, 140)

    def test_auto_now_add(self):
        tweet: Tweet = Tweet.objects.create(content='jiuzhangdafahao')
        old_created_time = tweet.created_at
        tweet.content = 'updated tweet'
        tweet.save()
        self.assertEqual(old_created_time, tweet.created_at)

    def test_str(self):
        user = User.objects.create(username='linghu', password='god')
        tweet: Tweet = Tweet.objects.create(
            user=user, content='jiuzhangdafahao')
        self.assertEqual(str(tweet.created_at) in str(tweet), True)
        self.assertEqual(tweet.user.username in str(tweet), True)
        self.assertEqual(tweet.content in str(tweet), True)

查看tweet发了多久

from django.db import models
from django.contrib.auth.models import User
from utils.time_helpers import utc_now
from datetime import datetime


class Tweet(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    content = models.CharField(max_length=140)
    created_at = models.DateTimeField(auto_now_add=True)

    @property
    def hours_to_now(self):
        return (utc_now() - self.created_at).seconds // 3600

 

2434 · 定义联合索引和默认的排序规则

为tweet添加索引,先按用户id排序,然后再按创建时间降序排序

from django.db import models
from django.contrib.auth.models import User


class Tweet(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    content = models.CharField(max_length=140)
    created_at = models.DateTimeField(auto_now_add=True)

    # write your code here
    class Meta:
        index_together = ('user', 'created_at')
        ordering = ('user', '-created_at')

同样看一下如何测试排序

from django.test import TestCase
from tweets.models import Tweet
from datetime import datetime, timezone
import random


class TweetTests(TestCase):

    def test_tweet_meta(self):
        self.assertEqual(len(Tweet._meta.index_together), 1)
        self.assertEqual(Tweet._meta.index_together[0], ('user', 'created_at'))

        self.assertEqual(Tweet._meta.ordering, ('user', '-created_at'))

    def test_tweet_ordering(self):
        for i in range(10):
            Tweet.objects.create(content='default tweet content')

        tweets = Tweet.objects.all()
        for index in range(len(tweets)-1):
            self.assertEqual(
                tweets[index].created_at > tweets[index+1].created_at, True)

        random_tweet: Tweet = tweets[random.randint(
            0, len(tweets)-1)]
        random_tweet.created_at = datetime(
            random.randint(2000, 2020), 6, 1, 0, 0, 0).replace(tzinfo=timezone.utc)
        random_tweet.save()

        tweets = Tweet.objects.all()
        for index in range(len(tweets)-1):
            self.assertEqual(
                tweets[index].created_at > tweets[index+1].created_at, True)

定义评论模型

 评论user和tweet作为外键,索引先按tweet排序,再按create_at排序

from django.db import models
from django.contrib.auth.models import User
from tweets.models import Tweet


class Comment(models.Model):
    # write your code here
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    tweet = models.ForeignKey(Tweet, on_delete=models.SET_NULL, null=True)
    content = models.CharField(max_length=140)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    # write your code here
    class Meta:
        index_together = ('tweet', 'created_at')

    def __str__(self):
        return f"{self.created_at} - {self.user} says {self.content} at tweet {self.tweet_id}"

2430 · 实现好友关系模型

这个除了索引以外,还需要有一个唯一约束,即不能关注同一个人两次。

from django.db import models
from django.contrib.auth.models import User


class Friendship(models.Model):
    # write your code here
    from_user = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        related_name='following_friendship_set',
    )
    to_user = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        related_name='follower_friendship_set',
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        index_together = (
            ('from_user_id', 'created_at'),
            ('to_user_id', 'created_at'),
        )
        unique_together = (('from_user_id', 'to_user_id'),)

    def __str__(self):
        return f'{self.from_user_id} followed {self.to_user_id}'

定义新鲜事模型

from django.db import models
from django.contrib.auth.models import User
from tweets.models import Tweet


class NewsFeed(models.Model):
    # write your code here
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    tweet = models.ForeignKey(Tweet, on_delete=models.SET_NULL, null=True)
    created_at = models.DateTimeField(auto_now_add=True)


    class Meta:
        index_together = ('user','created_at')
        unique_together = ('user', 'tweet')
        ordering = ('user', '-created_at')
        
    
    def __str__(self):
        return f"{self.created_at} inbox of {self.user}: {self.tweet}"

 定义点赞模型

from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models


class Like(models.Model):
    # write your code here
    content_type = models.ForeignKey(
        ContentType,
        on_delete=models.SET_NULL,
        null=True,
    )
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    # write your code here
    class Meta:
        index_together = ('content_type', 'object_id', 'created_at')
        unique_together = ('content_type', 'object_id', 'user')


    def __str__(self):
        return f"{self.created_at} - {self.user} liked {self.content_type} {self.object_id}"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值