I'm new to programming.
In my blog I want to show a list of categories.
If I create a queryset like this:
Category.objects.all()
my django-modeltranslation works perfectly.
But I want to get categories of only published posts. Then my queryset is:
Post.objects.values('category__name').filter(is_published=True)
However, django-modeltranslation doesn't work. I get values from 'name' field instead 'name_en' or 'name_ru' fields.
What is wrong?
Here's my models.py :
class Category(models.Model):
name = models.TextField(max_length=100)
url = models.SlugField(max_length=160, unique=True)
class Post(models.Model):
title = models.TextField('title', max_length=150)
category = models.ManyToManyField(Category, related_name='posts', blank=True)
I think you better query in reverse: with .values(…) you select a specific database column, so this will omit the model logic.
You can retrieve the categories with:
Category.objects.filter(posts__is_published=True).distinct()
Related
In my current project I am trying to set up a simple testing app in Django. For management I use the generated Django admin, but I struggle to include a sortable computed field with best test result in changelist view of a model.
My models are as follows (simplified):
class Candidate(models.Model):
name = models.CharField(max_length=255, null=False)
email = models.EmailField(unique=True, null=False)
class Test(models.Model):
candidate = models.ForeignKey(Candidate, on_delete=models.CASCADE, null=False)
result = models.PositiveIntegerField(null=True)
class Question(models.Model):
text = models.TextField(null=False)
correct_answer = models.CharField(max_length=1, choices=OPTIONS, null=False)
class Answer(models.Model):
test = models.ForeignKey(Test, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='answers')
answer = models.CharField(max_length=1, choices=Question.OPTIONS, null=True)
A candidate may have multiple tests and I want to display a field with his best result in the changelist view and be able to sort by it. The result is a percentage of correct answers (Answer.question.correct_answer == Answer.answer) out of all answers with the same test FK.
Discovered I cannot use a custom computed field defined by a function, because Django then cannot sort by it as sorting needs modification of a queryset which translates directly to SQL. So I added the Test.result field with calculated percentages (which denormalized the scheme :-/ ) and try to add annotated field in queryset with SELECT MAX(Test.result) FROM Test WHERE Test.candidate = {candidate} for every candidate, but cannot find a way how to do it.
The problem is, that the query needs reversed foreign key mapping, because of the 1:M mapping of candidate:test and I haven't found a way how to implement it. This is as far as I got:
class CandidateAdmin(admin.ModelAdmin):
list_display = ['name', 'email','best_result']
search_fields = ['name', 'email']
def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.annotate(
_best_result = models.Max('tests_result')
)
return queryset
def best_result(self, obj):
return obj._best_result
But Django doesn't understand my attempt use MAX on reversed foreign key search of tests_result. Could you advise? Or if I missed a way how to add custom sorting, so I don't need to keep the calculated test result in the database while still sorting by it, I'd be grateful for any hint.
In the end I created a database view with the query, added it to my models with managed = False in Meta and used that instead. Works like a charm.
I need to display unique values in template. I know distinct will work in query. But table in one row Many to Many field I don't know how to implement for that. If any possibilities are there to use it in template
class DoctorFeedback(models.Model):
visited_for = models.CharField(max_length=200)
tag = models.ManyToManyField(Tags)
class Tags(models.Model):
tag_title = models.CharField(max_length=50)
You can add unique=True to Tags, so there will never be any duplicates:
class Tags(models.Model):
tag_title = models.CharField(max_length=50, unique=True)
These are two models in my Django app :
models.py
class Posts(models.Model):
title = models.CharField(max_length=200, blank=True)
author = models.ForeignKey(user,on_delete=models.CASCADE,default=None, blank=True)
content = models.TextField()
class Unposted(models.Model):
article = models.ForeignKey(Posts, on_delete=models.CASCADE)
upload_at = models.DateTimeField(default=datetime.now, blank=True)
I'm trying to retrieve data from Posts using an API request to Unposted.
Here's what I have until now but I'm unsure how to get data from the Posts model. Right now I just get a JSON response with only the upload_at field.
resources.py
class UnpostedResource(ModelResource):
class Meta:
queryset = Unposted.objects.all()
resource_name = 'unposted'
If I'm not wrong, u can just import your Posts model and then just by for loop make an array with posts models using foreign key from unposted to filter your posts =) Sounds weird and I'm not sure about effectiveness, but looks pretty nice. It will look smth like:
queryset = Posts.objects.filter(article_in=[get(i.article) for i in Unposted.objects.all()])
In the case, Posts is a foreignkey of Unposted, thus you need to define foreignkey field in the resource for the corresponding field in model, this tutorial maybe can help you.
I'm new to Django so I make 3 simple tables to return a WishList. The thing is that I want whenever user asks for WishList, his/her user_id is used to make a SELECT query to return his/her own WishList. And I want to get product title and product url from my WishList table. I'm using to_field but with that way I only can get product title back. I don't know much about Django so help me!
Product
class Product(models.Model):
class Meta:
unique_together = (('id', 'title'),)
title = models.CharField(max_length=200, unique=True,
help_text='Name of the product')
url = models.CharField(max_length=300, default='',
help_text='Url of the product')
def __str__(self):
return 'Product: {}'.format(self.title)
WishList
class WishList(models.Model):
class Meta:
unique_together = (('user', 'product'),)
user = models.ForeignKey(fbuser,
on_delete=models.CASCADE,
help_text='Facebook user',
to_field='user_id')
product = models.ForeignKey(Product, to_field='title', db_column='title',
on_delete=models.CASCADE)
def __str__(self):
return 'WishList: {}'.format(self.user)
It's not a good practice to override to_field to another field different than your model.pk unless you have a really good reason and you know what you are doing (definitely not the case right now).
So after you read the docs, you will know that in order to get wishlisht related to a user, you can use the ForeignKey reverse relation to get all related wishlists for a user.
user_wishlists = my_user.wishlist_set.all()
#Because we know that you want to access the wishlist.products
#in order to optimize things (in terms of db queries)
#you can add and .select_related('product')
#e.g, user_wishlists = my_user.wishlist_set.all().select_related('product')
#now follow the wishlist.product foreign key to access the related product for every wishlist
for wishlist in user_wishlists:
product = wishlist.product
print (product.id, product.title, product.url)
Now after you read a little bit more of the documentation
you will notice that your WishList model is in fact an intermediate model for a ManyToMany relation between User and his wished products, then you will know that you can define a M2M field between user and products via WishList like so:
class FbUser(models.Model):
#...
wished_products = models.ManyToManyField(
Product,
through='WishList',
through_fields=('user', 'product')
)
#and now accessing user wished products would be easy as:
user_wished_products = my_user.wished_products.all()
for product in user_wished_products:
print (product.id, product.title, product.url)
Is there a way to de-couple django admin inline-models from clustering like models together?
A bit of context: I have a model named Page with two inline-models, TextBlock and GalleryContainer. I would to render TextBlocks and GalleryContainers on a template based on the order they're added in the Page admin editor. The default django-admin display looks like this:
I would like it to display as:
Gallery Container 1
Textblock 1
Gallery Container 2
But I have no idea how to do that. Any suggestions or nudges in the right direction would be a great help. Thanks in advance. (I also hope my question makes sense...)
If you want a relation between a column and a gallery your models should reflect that. So if I understand correctly: A page has name and columns. A column has text, gallery (optional) and ordering.
models.py:
class Page(models.Model):
name = models.CharField(max_length=200)
class Gallery(models.Model):
name = models.CharField(max_length=200)
class Column(models.Model):
page = models.ForeignKey(Page)
text = models.TextField()
gallery = models.ForeignKey(Gallery, null=True, blank=True) # Optional
ordering = models.IntegerField()
class Meta:
ordering = ('ordering', )
This example shows how ordering is done by an IntegerField. If you want to order the columns based on the moment they where added replace
ordering = models.IntegerField()
with
models.datetimeField(auto_now_add=True)
In your admin.py:
class ColumnInline(admin.TabularInline): # or StackedInline
model = Column
class PageAdmin(admin.ModelAdmin):
inlines = [
ColumnInline,
]
Note: I put your 'gallery display name' in Gallery as 'name'. Makes more sense to give the gallery it's name only once. But if a gallery is in more places with different names, than you need a field (e.g. 'gallery_display_name=models.CharField(max_lenght=200)') on the Column model.
Is this the answer to your question? I hope it helps!