我将PostImage模型中的One至Onefield更改为ForeignKey,并收到上述错误.

以下是更改后的内容:

class PostImage(models.Model):
# post = models.OneToOneField(Post, on_delete=models.CASCADE, related_name='image', null=True)
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='image', null=True)
image = ProcessedImageField(verbose_name=_('image'), s至rage=post_image_s至rage,
                            upload_至=upload_至_post_image_direc至ry,
                            width_field='width',
                            height_field='height',
                            blank=False, null=True, format='JPEG', options={'quality': 80},

Docker的日志(log)由以下几部分组成:

my-api        | Traceback (most recent call last):
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
my-api        |     response = get_response(request)
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
my-api        |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/views/decora至rs/csrf.py", line 54, in wrapped_view
my-api        |     return view_func(*args, **kwargs)
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
my-api        |     return self.dispatch(request, *args, **kwargs)
my-api        |   File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
my-api        |     response = self.handle_exception(exc)
my-api        |   File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
my-api        |     self.raise_uncaught_exception(exc)
my-api        |   File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
my-api        |     raise exc
my-api        |   File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
my-api        |     response = handler(request, *args, **kwargs)
my-api        |   File "/opt/my-api-core/my_posts/views/posts/views.py", line 55, in get
my-api        |     return self.get_posts_for_authenticated_user(request)
my-api        |   File "/opt/my-api-core/my_posts/views/posts/views.py", line 92, in get_posts_for_authenticated_user
my-api        |     post_serializer_data = AuthenticatedUserPostSerializer(posts, many=True, context={"request": request}).data
my-api        |   File "/usr/local/lib/python3.8/site-packages/rest_framework/serializers.py", line 768, in data
my-api        |     ret = super().data
my-api        |   File "/usr/local/lib/python3.8/site-packages/rest_framework/serializers.py", line 253, in data
my-api        |     self._data = self.至_representation(self.instance)
my-api        |   File "/usr/local/lib/python3.8/site-packages/rest_framework/serializers.py", line 686, in 至_representation
my-api        |     return [
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 280, in __iter__
my-api        |     self._fetch_all()
my-api        |   File "/usr/local/lib/python3.8/site-packages/cacheops/query.py", line 273, in _fetch_all
my-api        |     return self._no_monkey._fetch_all(self)
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 1324, in _fetch_all
my-api        |     self._result_cache = list(self._iterable_class(self))
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 51, in __iter__
my-api        |     results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1156, in execute_sql
my-api        |     sql, params = self.as_sql()
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 507, in as_sql
my-api        |     extra_select, order_by, group_by = self.pre_sql_setup()
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 55, in pre_sql_setup
my-api        |     self.setup_query()
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 46, in setup_query
my-api        |     self.select, self.klass_info, self.annotation_col_map = self.get_select()
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 227, in get_select
my-api        |     cols = self.get_default_columns()
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 671, in get_default_columns
my-api        |     only_load = self.deferred_至_columns()
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1096, in deferred_至_columns
my-api        |     self.query.deferred_至_data(columns, self.query.get_loaded_field_names_cb)
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/query.py", line 754, in deferred_至_data
my-api        |     callback(target, model, values)
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/query.py", line 2179, in get_loaded_field_names_cb
my-api        |     target[model] = {f.attname for f in fields}
my-api        |   File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/query.py", line 2179, in <setcomp>
my-api        |     target[model] = {f.attname for f in fields}
my-api        | AttributeError: 'ManyToOneRel' object has no attribute 'attname'
django.server ERROR    "GET /api/posts/?count=10& HTTP/1.1" 500 195670

根据上述日志(log),导致错误的函数:

def get_posts_for_authenticated_user(self, request):
        query_params = request.query_params.dict()
        normalize_list_value_in_request_data('circle_id', query_params)
        normalize_list_value_in_request_data('list_id', query_params)

        serializer = GetPostsSerializer(data=query_params)
        serializer.is_valid(raise_exception=True)
        data = serializer.validated_data

        circles_ids = data.get('circle_id')
        lists_ids = data.get('list_id')
        max_id = data.get('max_id')
        min_id = data.get('min_id')
        count = data.get('count', 10)
        username = data.get('username')

        user = request.user

        if username:
            if username == user.username:
                posts = user.get_posts(max_id=max_id)
            else:
                posts = user.get_posts_for_user_with_username(username, max_id=max_id, min_id=min_id)
        else:
            posts = user.get_timeline_posts(
                circles_ids=circles_ids,
                lists_ids=lists_ids,
                max_id=max_id,
                min_id=min_id,
                count=count
            )

        posts = posts.order_by('-id')[:count]

        post_serializer_data = AuthenticatedUserPostSerializer(posts, many=True, context={"request": request}).data

        return Response(post_serializer_data, status=status.HTTP_200_OK)

我try 了以下几点:

1.将Order_by()从

posts = posts.order_by('-id')[:count]

posts = posts.order_by('-created')[:count]

因为 docker 日志(log)里提到了伯爵.但是仍然得到了上述错误.

2.我甚至try 使用flush命令清除数据库.重新创建了 docker 集装箱.错误仍然存在.

推荐答案

AttributeError: 'ManyToOneRel' object has no attribute 'attname': that should mean that Django tries to access a field attribute that does not exist on a related model.
That error often occurs after changing relationships in models, as you did by changing a OneToOneField to a ForeignKey. (a bit as in "How to Update Django Model Relationship only with Foreign Key Value", even though the focus is on how to update a foreign key relationship in a Django model by directly using the primary key of the related model, rather than fetching the entire related model instance).

当你从OneToOneField切换到ForeignKey时,Django会以不同的方式处理这种关系.ManyToOneRel对象是Django内部的一个构造,表示从PostPostImage的反向关系.

由于该错误是在序列化期间发生的,因此请确保AuthenticatedUserPostSerializer正确处理post字段.如果序列化程序try 访问post字段上不存在的属性,则可能会导致此错误.查找序列化程序中可能将post.image视为单个实例而不是一组实例的任何部分.

你的ForeignKey分中有related_name='image'分.这意味着,在Post模型上,Django希望post.image返回多个PostImage实例.如果在代码(或序列化程序)中的任何地方将post.image视为单个实例(就像对待OneToOneField一样),则会导致错误.您可能需要调整此逻辑或将related_name更改为类似'images'的值,以反映多个实例.

ForeignKey中的related_name='image'现在应该反映post.image将返回一个包含PostImage个实例的查询集,而不是单个实例.考虑将其更改为'images',以更好地表示关系.

class PostImage(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='images', null=True)
    ...

更改字段类型后,请确保使用Django迁移正确更新数据库模式.有时,模型和数据库之间的不一致可能会导致意外错误.

最后,在get_posts_for_authenticated_user方法中添加调试信息以判断posts查询.

def get_posts_for_authenticated_user(self, request):
    ...
    posts = posts.order_by('-id')[:count]

    # Debugging: Print or log the query
    print("DEBUG: posts query", posts.query)

    post_serializer_data = AuthenticatedUserPostSerializer(posts, many=True, context={"request": request}).data

    return Response(post_serializer_data, status=status.HTTP_200_OK)

这些调试语句将帮助您了解在数据库查询级别发生的情况.密切关注您的控制台或日志(log)以查看输出.


我的目标是允许模型PostImage允许多个图像上传并将其链接到一个帖子.例如,具有多个图像的单个博客帖子.

Correct me if I am wrong, changing the related_name to 'images' with a ForeignKey to Post will allow for multiple instances of PostImages?
Because I do have code logic with the field 'image' inside post as you rightly mentioned. There is also a image = ProcessedImageField right below where I define the ForeignKey.

在调试之前需要注意的是,正如您提到的,我只是将"image"更改为"images",并在运行迁移后运行了一个GET请求.我现在得到:FieldDoesNotExist:Post没有名为"image"的字段

The related_name attribute in a ForeignKey relationship specifies the name to use for the reverse relation from the related model back to your model. In your case, by setting related_name='images' in the PostImage model, you are telling Django to use images to access related PostImage instances from a Post instance.
So, after this change, on any Post object, you can access its related PostImage objects using post.images.all().

是的,更改为ForeignKey并使用related_name='images'确实允许多个PostImage实例与单个Post相关联.对于一篇博客文章可能有多张图片的用例来说,这才是正确的方法.

The error FieldDoesNotExist: Post has no field named 'image' occurs because, in your views or serializers, you are likely still accessing image directly on a Post object. After the change in your model, you should update your code to use images.
Wherever you were accessing post.image, you should now use post.images.all() to get a queryset of all related PostImage objects.

更新以前依赖于post.image的任何视图、序列化程序或代码的其他部分.对于序列化,如果您需要在Post序列化程序中包含图像,则可以使用PostImage的嵌套序列化程序.

您的串行化程序可以是:

class PostImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = PostImage
        fields = ['image', ...]  # Include other fields as needed

class PostSerializer(serializers.ModelSerializer):
    images = PostImageSerializer(many=True, read_only=True)

    class Meta:
        model = Post
        fields = ['title', 'content', 'images', ...]  # Other Post fields

在任何型号更改后再次运行迁移:

python manage.py makemigrations
python manage.py migrate

Django相关问答推荐

Django中的Sync_to_Async修饰器、异步视图

Django和静态文件

如何在Django中显示文件大小

如何在uwsgi中创建单个日志(log)文件?

使用 Crispy Forms 时 Django 返回 'TemplateDoesNotExist'

有什么方法可以自动设置 Debug True Django application

初始填充 Django 表单

Django 视图 - 首先从调用应用程序的目录加载模板

在 Django 中提供大文件(高负载)

如何在 django-rest-framework 中为 API 使用 TokenAuthentication

Django:如何使用动态(非模型)数据预填充 FormView?

带有 Django 和 Python 的 Atlassian Bamboo - 可能吗?

has_object_permission 和 has_permission 有什么区别?

对 django 的 Http Delete 请求返回 301

Django ORM 能否以可靠的与后端无关的方式存储无符号 64 位整数(又名 ulong64 或 uint64)?

如何在 Django 中触发 500 错误?

在 Django 开发服务器中关闭静态文件的缓存

暂时禁用 Django 缓存

警告:找不到分发的 svn 位置==0.6.16dev-r0

Django - 保存新对象时如何获取 self.id?