Reverse Lookup in django joined tables does not work - python

I just created a model as follows:
class A(models.Model):
name = models.CharField(max_length=150)
slug = models.SlugField(max_length=200)
class Meta:
db_table = "ax"
class B(models.Model):
name = models.CharField(max_length=150)
slug = models.SlugField(max_length=200)
class Meta:
db_table = "bx"
class Z(models.Model):
a = models.ForeignKey(A, on_delete=models.CASCADE)
b = models.ForeignKey(B, on_delete=models.CASCADE)
class Meta:
db_table = "zx"
I want to get list of A.names when B.slug == input_str.
What I've tried in view.py so far:
def myView(request, input_str):
context = {
'inputs_list': A.objects.filter(bx__slug__startswith=input_str).select_related('ax').select_related('bx').values('name')
}
return render(request, 'app/my_template.html', context)
This returns an error:
Cannot resolve keyword 'bx' into field. Choices are:zx, id, name,
slug...
My Question:
What is the correct lookup for returning A.name if B.slug= input_str. Or better say, how filter A based on a column in B?😊
A.objects.filter(bx__slug__startswith=input_str).select_related('ax').select_related('bx').values('name')

Related

How to serialize only certain elements of M2M set of the object being serialized?

So I have these models:
class Group(models.Model):
name = models.CharField(max_length=255, blank=True, null=True, default=None)
class Member(models.Model):
name = models.CharField(max_length=255, blank=True, null=True, default=None)
group = models.ForeignKey(Group, related_name='members', on_delete=models.CASCADE)
is_deleted = models.BooleanField()
And these serializers:
class GroupSerializer(serializers.ModelSerializer):
members = MemberSerializer(many=True, read_only=True)
class Meta:
model = Group
fields = '__all__'
class MemberSerializer(serializers.ModelSerializer):
# some field defintions here
class Meta:
model = Member
fields = '__all__'
And view:
class GroupViewSet(viewsets.ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer
Now what I want to do basically, is not return "members" of Group that has is_deleted set to True.
So if I have a Group with 3 Member where 1 has is_deleted set to True, I want my serializer to return the Group with 2 Members.
How do I go about achieving this?
To achieve this you can override the members field in the GroupSerializer to return a filtered queryset
class GroupSerializer(serializers.ModelSerializer):
members = serializers.SerializerMethodField()
def get_members(self, obj):
qs = Members.objects.filter(group=obj, is_deleted=True)
serialized = MemberSerializer(qs, many=True)
return serialized.data
class Meta:
model = Group
fields = '__all__'
This will return the member objects with is_deleted=True for the specific group.
Use serializer method field in members serializer
https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
You can modify the MemberSerializer which only return the is_deleted false field.
class MemberSerializer(serializers.ModelSerializer):
is_deleted_false = = serializers.SerializerMethodField(read_only=True)
#staticmethod
def get_is_deleted_false(obj):
if obj.is_deleted == False:
return obj.is_deleted
else:
pass
class Meta:
model = Member
fields = ('id', 'name', 'group', 'is_deleted_false')

Django models NameERROR in the same file?

good day to everyone, i had the name error in this code, someone can explain me why, please???
category = models.ManyToManyField(Category) NameError: name 'Category' is not defined
from django.db import models
from datetime import datetime
# Create your models here.
class Store(models.Model):
business_name = models.CharField(max_length=100, null=False, verbose_name='Nombre')
nit = models.PositiveIntegerField(null=False,default=0,verbose_name='NIT')
category = models.ManyToManyField(Category)
def __str__(self):
return self.business_name
class Meta:
db_table = 'Store'
verbose_name = 'Tienda'
verbose_name_plural = 'Tiendas'
ordering = ['id']
class Category(models.Model):
name = models.CharField(max_length=150, verbose_name='Name')
def __str__(self):
return self.name
class Meta:
verbose_name = 'Categoria'
verbose_name_plural = 'Categorias'
ordering = ['id']
thanks for your comments
When python is reading the file, it gets to the category = models.ManyToManyField(Category) but doesnt know what Category is yet,
Move the Category class BEFORE Store, and all will work.

Order post by date

I've created a list of post and now I want order this list by date of publishing. If I use order_by(-post_publishing_date) in the view the shell show me this error:
NameError: name 'post_publishing_date' is not defined
models.py
class PostModel(models.Model):
post_title = models.CharField(max_length=70)
post_short_description = models.TextField(max_length=200)
post_contents = models.TextField()
post_publishing_date = models.DateTimeField(auto_now=False, auto_now_add=True)
post_author = models.ForeignKey(AuthorModel, on_delete=models.CASCADE, related_name="connected_author")
post_keyconcept = models.ManyToManyField(KeyConceptModel, related_name="connected_keyconcept")
slug = models.SlugField(verbose_name="Slug", unique="True")
post_highlighted = models.BooleanField(default=False)
def __str__(self):
return self.post_title
def get_absolute_url(self):
return reverse("singlepostManuscriptusView", kwargs={"slug": self.slug})
class Meta:
verbose_name = "Articolo"
verbose_name_plural = "Articoli"
views.py
class SinglePostGDV(DetailView):
model = PostModel
template_name = "manuscriptus_post_detail.html"
class ListPostGDV(ListView):
model = PostModel
template_name = "manuscriptus_home.html"
queryset = PostModel.objects.filter().order_by(-post_publishing_date)
urls.py
urlpatterns = [
path("it/blog/", ListPostGDV.as_view(), name="homeManuscriptusView"),
path("it/blog/<slug:slug>/", SinglePostGDV.as_view(), name="singlepostManuscriptusView"),
]
What I did wrong?
Ad hoc ordering
Well Python is correct. There is no identifier post_publishing_date, you pass the name of the column through a string, so:
class ListPostGDV(ListView):
model = PostModel
template_name = "manuscriptus_home.html"
queryset = PostModel.objects.filter().order_by('-post_publishing_date')
Define an inherent ordering on the model
Note that you can also give a model an "inherent" ordering in the Meta class:
class PostModel(models.Model):
post_title = models.CharField(max_length=70)
post_short_description = models.TextField(max_length=200)
post_contents = models.TextField()
post_publishing_date = models.DateTimeField(auto_now=False, auto_now_add=True)
post_author = models.ForeignKey(AuthorModel, on_delete=models.CASCADE, related_name="connected_author")
post_keyconcept = models.ManyToManyField(KeyConceptModel, related_name="connected_keyconcept")
slug = models.SlugField(verbose_name="Slug", unique="True")
post_highlighted = models.BooleanField(default=False)
def __str__(self):
return self.post_title
def get_absolute_url(self):
return reverse("singlepostManuscriptusView", kwargs={"slug": self.slug})
class Meta:
ordering = ['-post_publishing_date']
verbose_name = "Articolo"
verbose_name_plural = "Articoli"
If you do this, all queries to this model will implicitly be ordered by -post_publishing_date. So this means that you can not "forget" to order the objects properly.
So then you do not have to order it in the views. You can of course only define one such "inherent" ordering, and it is not clear if you want to use one here.
order_by argument should be string:
queryset = PostModel.objects.filter().order_by('-post_publishing_date')

Django serialization: AttributeError when attempting to get a value for field on serializer

I am getting the following error,
AttributeError: Got AttributeError when attempting to get a value for field devicedetails on serializer DISerializer.
The serializer field might be named incorrectly and not match any attribute or key on the Device instance.
Original exception text was: 'Device' object has no attribute 'devicedetails'.
My models.py :-
class DeviceInfo(models.Model):
vendor = models.CharField(max_length=250)
device_type = models.CharField(max_length=250)
modelname = models.CharField(max_length=100)
class Device(models.Model):
name = models.CharField(max_length=100, primary_key=True)
username = models.TextField()
password = EncryptedTextField()
deviceinfo = models.ForeignKey(DeviceInfo, null=True)
class DeviceDetails(models.Model):
device = models.ForeignKey(Device)
serial_number = models.CharField(max_length=100)
version = models.CharField(max_length=100)
serializer.py :-
class DeviceInfoSerializer(serializers.ModelSerializer):
class Meta:
model = DeviceInfo
fields = ("id", "vendor", "device_type", "modelname")
class DeviceSerializer(serializers.ModelSerializer):
class Meta:
model = Device
fields = ("name","username", "password", "deviceinfo")
class DeviceDetailsSerializer(serializers.ModelSerializer):
class Meta:
model = DevieceDetails
fields = ("device", "serial_number", "version")
class DISerializer(serializers.ModelSerializer):
deviceinfo = DeviceInfoSerializer(read_only=True)
devicedetails = DeviceDetailsSerializer(many=True)
class Meta:
model = Device
fields = ("name", "username", "password", "deviceinfo", "devicedetails")
views.py :-
def list(self, request):
list = Device.objects.all()
serializer = DISerializer(list, many=True)
You need to rename devicedetails field to devicedetails_set. Automatically generated reverse name for relation padded with _set:
devicedetails_set = DeviceDetailsSerializer(many=True)
or use related_name on DeviceDetails's device field:
device = models.ForeignKey(Device, related_name='devicedetails')
From the docs:
If you have not set a related name for the reverse relationship, you'll need to use the automatically generated related name in the fields argument. For example: track_set

Django Multiple GenericRelation related_name in admin

I'm tring to create a generic foreign key and reuse it multiple time inside the same model
The problem is that when I load the admin interface I got the 2 Inline fields that display the same data.
I tried to use an fk_name passing the related_name defined in the model but without luck
Here is the code any help is appreciate
model.py:
class TranslatedCharField(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
class Meta:
unique_together = ('object_id', 'lang')
lang = models.CharField(max_length=255, choices=LANGUAGES)
text = models.CharField(max_length=255)
class Evento(models.Model):
slug = generic.GenericRelation(TranslatedCharField, related_name="slug")
titolo = generic.GenericRelation(TranslatedCharField, related_name="title")
admin.py:
class TranslatedSlugInline(generic.GenericTabularInline):
extra = 0
model = TranslatedCharField
verbose_name = "Slug"
verbose_name_plural = "Slug"
class TranslatedTitoloInline(generic.GenericTabularInline):
extra = 1
model = TranslatedCharField
verbose_name = "Titolo"
verbose_name_plural = "Titolo"
class EventoAdmin(admin.ModelAdmin):
inlines = [
TranslatedSlugInline,
TranslatedTitoloInline,
]
admin.site.register(Evento, EventoAdmin)
this is the result:
as you can see the list of TranslatedCharField is duplicated for the 2 relations
unique_together = ('object_id', 'lang')
I think you want
unique_together = ('content_type', 'object_id', 'lang')
because object_id is not unique across models.
slug = generic.GenericRelation(TranslatedCharField, related_name="slug")
titolo = generic.GenericRelation(TranslatedCharField, related_name="title")
"related_name" is how the TranslatedCharField can access in the other direction, i.e. by which attribute name you want it to access that Evento. "slug_event" and "title_event" more fitting.
ok I'd reviewed the things a but and the result is the follow:
class TranslatedCharField(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
relation_field = models.CharField(max_length=255)
class Meta:
unique_together = ('object_id', 'lang', 'relation_field')
lang = models.CharField(verbose_name="lingua", max_length=255, choices=LANGUAGES)
text = models.CharField(verbose_name="testo", max_length=255)
def translatedFieldInlineAdminFormFactory(relation_field, translatemodel):
class TranslatedFieldInlineAdminForm(forms.ModelForm):
class Meta:
model = translatemodel
def clean(self):
self.cleaned_data["relation_field"] = relation_field
return self.cleaned_data
class TranslatedTabularInline(generic.GenericTabularInline):
def __init__(self, *args, **kwargs):
super(TranslatedTabularInline, self).__init__(*args, **kwargs)
self.form = translatedFieldInlineAdminFormFactory(self._relation_field_filter, self.model)
extra = 1
max_num = len(LANGUAGES)
exclude = ('relation_field',)
model = None
_relation_field_filter = None
return TranslatedFieldInlineAdminForm
In this way when I need multiple TranslatedCharField I do the following
on the admin:
class TranslatedSlugInline(TranslatedTabularInline):
model = TranslatedCharField
_relation_field_filter = "slug_event_portal"
verbose_name = "Slug"
verbose_name_plural = "Slug"
class TranslatedSlugInline(TranslatedTabularInline):
model = TranslatedCharField
_relation_field_filter = "slug2_event_portal"
verbose_name = "Slug2"
verbose_name_plural = "Slug2"
thanks to the clean method a specific _relation_field_filter is used for each inline
this allow me at least to save them distinguished and retrive them useing the custom queryset
I'm still working on the Model of the Evento to retrive the specific set of values instead the whole related fields but I think I'm not too far now

Categories