I'm using django-favorites from https://bitbucket.org/last_partizan/django-favorites/overview, and I set everything right and when I run the code it gave me 'FavoriteManager' object has no attribute 'get_query_set'. The error was occuring from the django-favorites models.py from this line
qs = self.get_query_set().filter(content_type=content_type, object_id=obj.pk)
So I thought, I need to specify object. So I'm trying to use fav button for all my Post, so I need to change obj to Post. But even after changing I get same error. What is going on with this?
This is models.py inside favorite app, where error is occurring
def favorites_for_object(self, obj, user=None):
""" Returns Favorites for a specific object """
content_type = ContentType.objects.get_for_model(type(obj))
qs = self.get_query_set().filter(content_type=content_type,
object_id=obj.pk)
if user:
qs = qs.filter(user=user)
return qs
This is where I'm calling fav_item
<div class="actions">{% fav_item post user %}</div>
Lets say I want to put fav_item on my category model
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
slug = models.CharField(max_length=100, unique=True)
author = models.OneToOneField(settings.AUTH_USER_MODEL, unique=True)
def save(self, *args, **kwargs):
self.slug = uuslug(self.name,instance=self, max_length=100)
super(Category, self).save(*args, **kwargs)
def __unicode__(self):
return self.name
Then doesn't it make sense to import
main.models import Category
and switch obj to Category. Unfortunately there's not much documentation here: https://bitbucket.org/last_partizan/django-favorites/overview
This problem is related to Django version. The method get_query_set has been removed from Django 1.8.x . Before that, this method was used by RenameManagerMethods. Check this github source: https://github.com/django/django/blob/stable/1.7.x/django/db/models/manager.py#L56
Also django-favorites was last updated in 2013, as I can see from the source. You should consider downgrading your Django version.
Related
I am developing a Django 2.0 project app. It has a (non-working) models.py file, which looks something like this:
from django.db import models
from django.utils import timezone
class Computer(models.Model):
name = models.CharField(max_length=25)
def __str__(self):
return "Computer {}".format(self.name)
class Software(models.Model):
name = models.CharField(max_length=25)
description = models.CharField(max_length=1024, blank=True)
def __str__(self):
return self.name
class SoftwareVersion(models.Model):
software = models.ForeignKey(Software, on_delete=models.CASCADE, related_name="versions")
version = models.CharField(max_length=100)
released_at = models.DateTimeField(default=timezone.now)
def __str__(self):
return "{} {}".format(self.software, self.version)
class ComputerSoftwareBundle(models.Model):
computer = models.ForeignKey(Computer, on_delete=models.CASCADE, related_name="bundles")
installed_at = models.DateTimeField(default=timezone.now)
versions = models.ManyToManyField(SoftwareVersion, through="BundleSoftwareVersion", related_name="bundles")
class BundleSoftwareVersion(models.Model):
bundle = models.ForeignKey(ComputerSoftwareBundle, on_delete=models.CASCADE)
version = models.ForeignKey(SoftwareVersion, on_delete=models.CASCADE)
class Meta:
unique_together = (("bundle", "version__software"),)
The app tracks software bundles currently or previously installed on computers. The thing here is that a bundle should not contain more than one version of the same software. Also, SoftwareVersion should contain a reference to Software, because the same version string has a different meaning for different pieces of software.
The code does not work as described in this Stackoverflow answer. I left the unique_together line in to illustrate what I am trying to achieve.
I've tried to work around this limitation of Django (not being able to use fields referred to via a foreign key in unique_together) by overriding the save and validate_unique methods in BundleSoftwareVersion but that did not work out completely well. Here's the implementation I have tried:
class BundleSoftwareVersion(models.Model):
bundle = models.ForeignKey(ComputerSoftwareBundle, on_delete=models.CASCADE)
version = models.ForeignKey(SoftwareVersion, on_delete=models.CASCADE)
def save(self, *args, **kwargs):
self.validate_unique()
super().save(*args, **kwargs)
def validate_unique(self, exclude=None):
super().validate_unique(exclude)
bundle_versions = BundleSoftwareVersion.objects.filter(bundle=self.bundle,
version__software=self.version.software)
count = len(bundle_versions)
if not self.pk:
# if this instance is not stored in the database,
# we need to increment the count to take this instance
# into account
count += 1
if count > 1:
raise ValidationError("There already is an instance of software '{}' in this bundle.".format(self.version.software))
I have thus far tried out these models via the admin site. The checks work when changing an existing ComputerSoftwareBundle (the admin site displays a message next to the offending entry), but adding results in an uncaught exception.
Is there a better way to enforce this kind of uniqueness?
I have come up with a workaround:
class BundleSoftwareVersion(models.Model):
bundle = models.ForeignKey(ComputerSoftwareBundle, on_delete=models.CASCADE)
version = models.ForeignKey(SoftwareVersion, on_delete=models.CASCADE)
_software = models.ForeignKey(Software, on_delete=models.CASCADE, null=True, editable=False)
class Meta:
unique_together = (("bundle", "_software"),)
def save(self, *args, **kwargs):
self._software = self.version.software
super().save(*args, **kwargs)
As you can see, I now have a helper field _software which is used in unique_together and into which the self.version.software is stored on each save.
So far, I have experienced one downside with this approach: trying to save a ComputerSoftwareBundle containing duplicate software instances results in an error page for IntegrityError being displayed instead of an error message within the form.
I would appreciate suggestions on how to fix this downside, or even suggestions for a different approach altogether.
I'm new with django. I'm really confused with views filters.
Here is my models.py:
class Author(models.Model):
title = models.CharField(max_length=30)
user=models.ForeignKey(User)
age= models.CharField(max_length=2)
post= models.ManyToManyField(Article)
def __str__(self):
return self.title
def __str__(self):
return self.post
def __str__(self):
return self.age
class Meta:
ordering = ('title','user',)
Here is my views.py:
def posting(request):
details = Author.age.get(pk=request.user.id)
return render(request,'home.html' , {'detail':details})
Now I need to get the current logged in user (age or title or post). When I execute the code I get the above error. How can I filter the particular object of logged in user?
Kindly suggest me some docs for views filter.
You access fields after returning a model instance via the manager (default manager is named objects), not directly:
author = Author.objects.get(user=request.user)
age = author.age
Talking about some docs, the Django documentation is a good starting point.
In Django Admin I am displaying a url.
This url is created using the id the object that it is attached to.
I'm using python, django and django-rest-framework.
In my views I have logic on the ApiDetail class. Here I override the 'get' method.
I increment the current object in views.py:
currentObject = Api.objects.get(id=pk)
currentObject.currentNumber += 1
currentObject.save()
return self.retrieve(request, *args, **kwargs)
In models.py I set the url field:
class Api(models.Model):
myUrl = models.CharField(max_length=500, blank=True, verbose_name="Url", editable=False)
def save(self, *args, **kwargs):
self.formUrl = "https://custumUrl/"+str(self.id)+"/"
super(Api, self).save(*args, **kwargs)
Here I override the api save method to update the formUrl field.
The problem I have is when a form is first added to Django admin and saved the url says:
https://custumUrl/none/
It should say:
https://custumUrl/1/
Or any number, but definitely the number of the objects id.
I think Daniel is right in their comments and you should follow their advice.
But if you don't want to do that, then you should first save an object, then assign an id value to the url, then save it again:
class Api(models.Model):
myUrl = models.CharField(max_length=500, blank=True, verbose_name="Url", editable=False)
def save(self, *args, **kwargs):
super(Api, self).save(*args, **kwargs)
self.formUrl = "https://custumUrl/"+str(self.id)+"/"
super(Api, self).save(*args, **kwargs)
Is currentNumber defined in he Api class?
Also, in your Api class, you have myUrl defined, but in the save method it's formUrl.
Maybe try something like this:
class Api(models.Model):
formUrl = models.CharField(max_length=500, blank=True, verbose_name="Url", editable=False)
def save(self):
"""If this is the firsts time populate required details, otherwise update it."""
if not self.id:
latest_obj = Api.latest('id')
this_id = latest_obj.id
self.formUrl = "https://custumUrl/"+str(this_id)+"/"
super(Api, self).save()
else:
#Save it as is
super(Api, self).save()
this question might get a bit large,i will try to explain perrty much everything whats going on.below is my heading model which fills the slug field itself by whatever is the title:
class Heading(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=5000)
content =RichTextUploadingField ()
image= models.ImageField(null=True,blank=True)
date = models.DateField(default=datetime.now())
time = models.TimeField(default=datetime.now())
slug = models.SlugField(unique=True, null=True, blank=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Heading, self).save(*args, **kwargs)
my title is in a foreign language(nepali language to be specific)
below is the image of my admin panel to fill up the heading class
as you can see my title is in foreign language but my slug field is filled automatically by converting that title in english language which is not what i want,i want my slug field to be filled in the same language as my title field.i did some search and a module called unidecode might be the solution to it,i tried using it too but since its documentation is not well i couldn't get hook of it.so if there is any other solution or how to make proper use of unidecode?any kind of help or clue would be greatly appreciated
The problem is, slugification happens in JavaScript (at least in the standard Django admin), before it reaches the server (you can look up urlify.js in the admin contrib package).
There's a new option on SlugField called allow_unicode, which might do what you want, but it's been introduced in Django 1.9.
If you cannot upgrade to 1.9 yet, you could in theory set up some endpoint on your server that would take a string, run unidecode on it, and return it, and then cook up some custom JavaScript code that would override the default slugification in the admin, but that sounds like quite a lot of work.
Another option would be to hide the slug field from the admin altogether, and do something similar to that snippet of code you posted in your question, except you should probably do this in the ModelAdmin class instead of the model itself (and you probably want to use unidecode there before passing the string to slugify).
Firstly you have to import "SLUGIFY" [from django.utils.text import slugify].
Secondly, In model,
slug = models.SlugField(allow_unicode=True, unique=True, null=True,
blank=True)
After that:
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
if not self.slug:
slug_str = f"{self.title}"
self.slug = slugify(slug_str, allow_unicode=True)
super(Blog, self).save(*args, **kwargs)
Finally Don't forget to add
[ALLOW_UNICODE_SLUGS = True]
in settings.py.
Banging head against the wall again.
I'm trying to add tags using other known fields
# models.py
class MyModel(models.Model):
...
tags = models.ManyToManyField(Tag, blank=True)
field_m2m = models.ManyToManyField('M2mModel', blank=True)
field_fk = models.ForeignKey('FkModel', blank=True, null=True)
...
def save(self, *args, **kwargs):
for inst in self.field_m2m.all():
self.tags.add(Tag.objects.get(name=inst.name))
self.tags.add(Tag.objects.get(name=self.field_fk.name))
super(MyModel, self).save(*args, **kwargs)
class FkModel(models.Model):
name = models.CharField(max_length=255, unique=True)
...
class M2mModel(models.Model):
name = models.CharField(max_length=255, unique=True)
...
I am 100% sure my field_m2m and field_fk aren't empty and what's not less important: there are instances corresponding to EXISTING tags. I have other functions covering this part well. I have also tried hardcoding the strings (Tag.objects.get(name="mystring")) to be 101% sure.
Yet, no tags are assigned through admin panel.
I tried to go through the steps in shell and it works there.
>>> m = MyModel.objects.get(name='something')
>>> t = Tag.objects.get(name='sometag')
>>> m.tags.add(t)
>>> m.tags.all()
[<Tag: sometag>]
How to make it work from save() method?
Also until the the model instance is created for the first time, traceback is complaining about: "<MyModel: Something>" needs to have a value for field "mymodel" before this many-to-many relationship can be used.
I guess I should save the model instance before even doing aforementioned assignments, right? How can I do it all at once?
Seems to me that your MyModel instance must be saved into database before saving any relationships. It makes sense because for the relationships, the MyModel's id is needed. So you can change the order of the save method like this:
def save(self, *args, **kwargs):
# notice that super class save go first.
super(MyModel, self).save(*args, **kwargs)
# also this cicle doesn't make sense since self is a newly
# created instance so it won't have anythin in field_m2m.all()
for inst in self.field_m2m.all():
self.tags.add(Tag.objects.get(name=inst.name))
# this should work ok if get returns any tag.
self.tags.add(Tag.objects.get(name=self.field_fk.name))
Hope this helps!
Figured it out thanks to this hint: https://stackoverflow.com/a/6200451/1344854
Model save() method stays default. First I tied a tag to my FkModel and M2mModel instances. The rest of the job is done in ModelAdmin.
# models.py
class FkModel(models.Model):
name = models.CharField(max_length=255, unique=True)
tag = models.ForeignKey(Tag, blank=True, null=True, related_name='fk')
...
class M2mModel(models.Model):
name = models.CharField(max_length=255, unique=True)
tag = models.ForeignKey(Tag, blank=True, null=True, related_name='m2m')
...
# admin.py
class MyModelAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
form.save() # as I learned, without saving at this point, obj.field_m2m.all() will be empty
tags = []
if obj.field_m2m.all():
tags += [m2m.tag for m2m in obj.field_m2m.all()]
if obj.field_fk:
tags += [obj.field_fk.tag]
form.cleaned_data['tags'] = tags
super(MyModelAdmin, self).save_model(request, obj, form, change)