How to use MPTT for django to get all children? - django

I'm trying to get all the children of a category:
def list_sub(self, category_name):
# this will return the parent if exists
category = Category.objects.filter(seo_title__exact = seo_title).filter(lang__exact = 'pt-PT').filter(level__exact = 1)
if category:
# but this doesn't work and in the documentation there are no examples
# of how to get it. See link about the method
sub_categories = category.get_children()
http://django-mptt.github.com/django-mptt/models.html#get-children
Update1:
qc = Category.objects.filter(seo_title__exact = cat).filter(lang__exact = 'pt-PT').filter(level__exact = 1)
category = qc.get()
if category:
qsc = category.get_children()
sub_categories = qsc.get()
now I get this error: "get() returned more than one Category -- it returned 7! Lookup parameters were {}"
thanks

Your problem is not with MPTT. The issue is that category is a queryset, not an instance - get_children() is an model method, not a queryset method.
Use get instead of filter.

Related

filtering a queryset, applying more than one filter

My models are:
models.User:
id = pk
username = text
models.Offer
id = pk
description = text
publicationDate = Date
user = Fk(User)
my serializer is:
class UserOfferSerializer(ModelSerializer):
offers = OfferSerializerAll(many=True, read_only=True)
class Meta:
model = User
fields = ('id', 'username', 'offers')
I am trying to apply more than one filter on the queryset:
users = users.filter(offers__publicationDate__range=[startdate, enddate]). prefetch_related(Prefetch('offers', queryset=Offer.objects.filter(
publicationDate__range=[startdate, enddate]))).distinct()
then
users = users.filter(offers__description__icontains=sometext).prefetch_related(Prefetch('offers', queryset=Offer.objects.filter(description__icontains=sometext))).distinct()
First one works fine and the other one throws the following exception:
ValueError: 'offers' lookup was already seen with a different queryset. You may need to adjust the ordering of your lookups.
Update:
My current code is:
if (offerBeginDate != None and offerEndDate != None):
b = offerBeginDate.split('-')
e = offerEndDate.split('-')
startdate = datetime.date(int(b[0]), int(b[1]), int(b[2]))
enddate = datetime.date(int(e[0]), int(e[1]), int(e[2]))
users = users.filter(offers__publicationDate__range=[startdate, enddate])
offers = offers.filter(publicationDate__range=[startdate, enddate])
if (descriptionText != None):
users = users.filter(offers__functionDescription__icontains=descriptionText.strip())
offers = offers.filter(functionDescription__icontains=descriptionText.strip())
users = users.prefetch_related('offers', Prefetch(queryset=offers))
Any help? Thank you all :)))
You can use to_attr argument of Prefetch object to prefetch additional queryset:
users = users.filter(offers__description__icontains=sometext).prefetch_related(
Prefetch('offers', queryset=Offer.objects.filter(
publicationDate__range=[startdate, enddate]), to_attr='date_offers'),
Prefetch('offers', queryset=Offer.objects.filter(description__icontains=sometext), to_attr='description_offers')).distinct()
UPD
If you need dynamically add filters to prefetched queryset you can define it separately like this:
if some_case:
users = users.filter(offers__description__icontains=sometext)
offers=Offer.objects.filter(description__icontains=sometext)
if some_case_2:
users = users.filter(**conditions)
offers = offers.filter(**conditions)
users = users.prefetch_related(Prefetch('offers', queryset=offers))
Now each user in users queryset will have two attributes: user.date_offers and user.description_offers.

Django : get() returned more than one

I have trouble to get my data from DB.
Basically one teacher can create more no of class_room each class_room contains a title and it has more number of students.
models.py
class class_room(models.model):
user = models.ForeignKey(User,related_name = 'classroom')
title = models.charField(max_length=50)
students = models.ManyToManyField(User,related_name= 'commits',symmetrical=FAlSE)
views.py
def index(request):
user = request.user
Total_class = class_room.objects.get(user = user)
students_list = Total_class.students.all()
class_name = Total_class.title.all()
return render(request,'trial/index.html,{'Total':Total_class ,'no':students_list, 'class_name ':class_name )
When i try to execute this code. i get this error get() returned more than one
Then i removed get() bcoz the user has more number of class_room so i put filter() After that i get 'QuerySet'object has no attribute 'students'
Any help appreciated :(
You have multiple objects for model class_room in the database, with the same user. Either you need to enforce the uniqueness to the user attribute in the models.
Or, you can get the students attribute of the first object in the query like,
Total_class = class_room.objects.filter(user = user).first()
students_list = Total_class.students.all()
or using index,
Total_class = class_room.objects.filter(user = user)[2]
#any element.
EDIT
As per the request of OP, I think the required queryset would be,
student_list = User.objects.filter(class_room__user=request.user)

Want to hide error message (View)

I'm matching the name in Album Model. And Its working just fine. But Some time It does not match. And It raise error message Album matching query does not exist. I want if no match is found. Then don't display any error message. Is it possible? Thanks
def movie_details(request,slug):
movies = get_object_or_404(Movie,slug=slug)
# calculating wikipedia directory structer for images
#image_name = movies.image
name = movies.title
album_name = Album.objects.get(name__exact=name)
album_id = album_name.id
song_list = Song.objects.filter(album=album_id)
#image_path = generateWikiImage(image_name)
#
return render_to_response('base_movies.html',locals(),
context_instance=RequestContext(request)
)
Error message
Album matching query does not exist
UPDATE:
def movie_details(request,slug):
movies = get_object_or_404(Movie,slug=slug)
# calculating wikipedia directory structer for images
#image_name = movies.image
name = movies.title
try:
album_name = Album.objects.get(name__exact=name)
album_id = album_name.id
song_list = Song.objects.filter(album=album_id)
except:
pass
Thanks F.C.
As suggested in the comment above, you need to catch the exception that's raised. In your case, it'd be:
try:
album_name = Album.objects.get(name__exact=name)
except Album.DoesNotExist:
pass
If you want to set album_name to some default value if you can't find it, replace pass with code to set it to your default value.
(This StackOverflow post also deals with a similar issue.)

Set default value for dropdown in django forms

I am unable to set default value for a dropdown while loading forms.
Here is the code
state = forms.TypedChoiceField(choices = formfields.State)
State = (
('QC_APPROVED','QC_APPROVED'),
('REVERT','REVERT'),
('FIXED','FIXED'),
)
If I want to make the default state as FIXED. I am writing this code
state = forms.TypedChoiceField(choices = formfields.State, default = 'FIXED')
If I execute the above code I am getting the below error.
Exception Value: __init__() got an unexpected keyword argument 'default'
Can some one help on this?
state = forms.TypedChoiceField(choices=formfields.State, initial='FIXED')
As shown in documentation: http://docs.djangoproject.com/en/dev/ref/forms/fields/#initial
I came across this thread while looking for how to set the initial "selected" state of a Django form for a foreign key field, so I just wanted to add that you do this as follows:
models.py:
class Thread(NamedModel):
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
title = models.CharField(max_length=70, blank=False)
forms.py:
class ThreadForm(forms.ModelForm):
class Meta:
model = Thread
fields = ['topic', 'title']
views.py:
def createThread(request, topic_title):
topic = Topic.getTopic(topic_title)
threadForm = ThreadForm(initial={'topic': topic.id})
...
The key is setting initial={'topic': topic.id} which is not well documented in my opinion.
fields take initial values
state = forms.TypedChoiceField(choices=formfields.State, initial='FIXED')
title = forms.CharField(widget=forms.Select(choices=formfields.State) , initial='FIXED')
toppings = forms.ChoiceField(
widget=forms.Select(attrs={'class':"hhhhhhhh"}),
choices = formfields.State,
initial='FIXED'
)
If the other solutions dont work for you,Try this:
It turns out that ModelChoiceField has an attribute called empty_label.With empty _label you can enter a default value for the user to see.
Example: In forms.py
Class CreateForm(forms.ModelForm):
category = forms.ModelChoiceField(empty_label="Choose Category")
Try the number:
state = forms.TypedChoiceField(choices = formfields.State, default = 2 )

Django SELECT (1) AS [a] FROM [my_table] WHERE ([my_table].[id] = ? AND NOT ([my_table].[id] = ? )) (1, 1)

Why is Django executing statements such as this:
SELECT (1) AS [a] FROM [my_table]
WHERE ([my_table].[id] = ?
AND NOT ([my_table].[id] = ? )) (1, 1)
This happens when calling is_valid() on a formset created the following way:
MyFormSet = modelformset_factory(Table, fields=['my_field'], extra=0)
my_form_set = MyFormSet(request.POST,
queryset=Table.objects.all())
where Table and MyForm are as simple as, say:
class Table(models.Model):
my_field = models.CharField(max_length=10)
class MyForm(forms.ModelForm):
class Meta:
model = Table
Hint: I looked at the call stack and the code responsible for it (in django/forms/models.py) is below:
def _perform_unique_checks(self, unique_checks):
import pdb; pdb.set_trace()
bad_fields = set()
form_errors = []
for unique_check in unique_checks:
# Try to look up an existing object with the same values as this
# object's values for all the unique field.
lookup_kwargs = {}
for field_name in unique_check:
lookup_value = self.cleaned_data[field_name]
# ModelChoiceField will return an object instance rather than
# a raw primary key value, so convert it to a pk value before
# using it in a lookup.
if isinstance(self.fields[field_name], ModelChoiceField):
lookup_value = lookup_value.pk
lookup_kwargs[str(field_name)] = lookup_value
qs = self.instance.__class__._default_manager.filter(**lookup_kwargs)
# Exclude the current object from the query if we are editing an
# instance (as opposed to creating a new one)
if self.instance.pk is not None:
qs = qs.exclude(pk=self.instance.pk)
Basically the pk is both included for the uniqueness check and excluded. Looks like Django can be smarter and avoid such inefficiency.
I haven't looked at it in detail, but I think you are right that Django could shortcut this query. Please file a ticket at http://code.djangoproject.com/.
Looks like this has been fixed already in trunk (by adding new functionality that also fixes this particular problem)