In Django, Why does my database manager fail? - python

I am learning managers for the first time.
I am trying to figure out how to set these managers correctly. It appears that managers are similar in philosophy as a SQL View.
Here is my manager and class:
class SubscriptionManager(models.Manager):
def active_officers(self):
officers = self.get_queryset().filter(Modified__gte=datetime.now()-timedelta(days=365)).filter(Subscription_Type='O')
return officers
def lifer(self):
return self.get_queryset().filter(Lifetime=True)
class Subscription(models.Model):
SType = (
('C', 'Civilian'),
('E', 'Enlisted'),
('O', 'Officer'),
)
Subscription_Type = models.CharField(max_length=1, choices=SType)
Lifetime = models.BooleanField(default=False)
Member = models.ForeignKey(Member)
Modified = models.DateField()
objects = SubscriptionManager()
def __str__(self):
return self.Member.first_name + " " + self.Member.last_name + ": " + self.Subscription_Type + "; last modified: " + self.Modified.strftime('%Y-%m-%d')
Once set I can still execute Subscription.objects.all() with no problems, bu if I fire off Subscription.objects.lifer(), I receive the following error: AttributeError: 'Manager' object has no attribute 'lifer'
I'm in python 3.4. What am I missing?
Thanks

Your code that you pasted above is correct and it works for me after copy and pasting.
Somewhere else in your code you have it listed as an attribute I believe Subscription.objects.lifer instead of the method Subscription.objects.lifer() Give that a search and I believe that should clear your error.

Related

How to do f string for exec?

This is my Django app name SFC
This is its models.py:
from django.db import models
import time
color = (
('1','果盤'),
('3','港灣'),
('5','輕快感'),
('6','鵝卵石'),
('7','調味料'),
('8','農收'),
('9','開瓶'),
('10','潛水'),
)
# The Chinese in the tuple name color is a noun describe the color.
# Create your models here.
class class_site(models.Model):
school_name = models.CharField("學校英文縮寫",max_length=10,default='CKJH')
Class = models.CharField("班級",max_length=5,default='802')
page_name = models.CharField("網頁名稱",max_length=10,default='八我啊二班')
color = models.CharField('配色',max_length=8,choices=color,default="6")
logo = models.ImageField('網站logo',null=True)
def __str__(self):
return self.school_name+self.Class+self.page_name
and it's another app name WT
This is its models.py:
from django.db import models
from SFC.models import class_site
# Create your models here.
for i in class_site.objects.all():
code=f'''class {i.school_name + i.Class}subject(models.Model):
subject = models.CharField('科目名',max_length=10)
class {i.school_name + i.Class}WorkType(models.Model):
subject = models.ForeignKey({i.school_name + i.Class}subject , on_delete=models.CASCADE)
work_name = models.CharField('功課名稱',max_length=10,default='習作')
common_name = models.CharField('功課俗名',max_length=10,default='國習')
class {i.school_name + i.Class}ExamType(models.Model):
subject = models.ForeignKey({i.school_name + i.Class}subject , on_delete=models.CASCADE)
work_name = models.CharField('考試名稱',max_length=10,default='大卷')
common_name = models.CharField('功課俗名',max_length=10,default='國卷')
'''
exec(code)
It send me:
class CKJH802WorkType(models.Model):
^
IndentationError: unindent does not match any outer indentation level
I tried not to use f string but i tkink it may be work by using f string.
What's wrong with models.py of WT?
The reason I don't use the foreignkey is because the site is for other people to use, It may cause some mistake.
This is website for education and everyone can ask for create his own class website, it will creates a new class website for him. It can lets the person in charge of the class enter the homework daily.If someone makes the mistake , it would influences the website for other class.
Use textwrap.dedent(text) to handle the indentation from the left side.
Your code:
code=f'''class {i.school_name + i.Class}subject(models.Model):
subject = models.CharField('科目名',max_length=10)
class {i.school_name + i.Class}WorkType(models.Model):
subject = models.ForeignKey({i.school_name + i.Class}subj
is basically this:
class ...:
subject = ...
class ...:
subject = ...
which is causing the indentation error and should look like this:
code=f'''
class {i.school_name + i.Class}subject(models.Model):
subject = models.CharField('科目名',max_length=10)
class {i.school_name + i.Class}WorkType(models.Model):
subject = models.ForeignKey({i.school_name + i.Class}subj
or:
code=f'''\ # to skip the initial empty first line
class {i.school_name + i.Class}subject(models.Model):
subject = models.CharField('科目名',max_length=10)
class {i.school_name + i.Class}WorkType(models.Model):
subject = models.ForeignKey({i.school_name + i.Class}subj
Also, if you really need to solve it this way, try to use metaclasses instead of the combination of exec() + F-strings as it just asks for an exploitation or a nasty bug. Otherwise, just try to use foreign keys or other, saner approach to DB structure + ORM.

Mongoengine: mongoengine.errors.FieldDoesNotExist

I've been confused with this error. I'm creating a Vehicle database with mongoengine that goes like this.
class Vehicles(Document):
make: StringField()
model: StringField()
license: StringField()
year: IntField()
mileage: IntField()
deleted: BooleanField()
for j in range(2):
vehicle = Vehicles(
make="Honda",
model="Civic",
license="H54 " + str(i) + str(j),
year=2015,
mileage= 500 + (i * 500),
deleted=False
).save()
While I try running the code, I've been getting:
mongoengine.errors.FieldDoesNotExist: The fields "{'license', 'year', 'model', 'mileage', 'make', 'deleted'}" do not exist on the document "Vehicles"
I don't understand why it's giving me this error. I know a solution is to change Document into DynamicDocument, but I don't really see why. Can someone please explain to me this error???
You are writing your class as if it was a dataclass but Mongoengine has no support for type hinting so it is not intepreting that correctly. MongoEngine is in fact currently not seeing any of your field definitions.
Turn your ":" into "=" and it should be fine
class Vehicles(Document):
make = StringField() # instead of 'make : StringField()'
...

queryset Q filter? Q get? how to get 'pk'

I'm trying to make a chatting room. and here is my code.
def make_chatroom(request, user_one, user_two):
user_one = user_models.User.objects.get_or_none(pk=user_one)
user_two = user_models.User.objects.get_or_none(pk=user_two)
if user_one is not None and user_two is not None:
try:
conversation = models.Conversation.objects.filter(
participants=user_one
).filter(participants=user_two)
print(conversation)
except models.Conversation.DoesNotExist:
conversation = models.Conversation.objects.create()
conversation.participants.add(user_one, user_two)
return redirect(reverse("conversations:detail", kwargs={"pk": conversation.pk}))
but
'QuerySet' object has no attribute 'pk'
error occur.
user_one is exist, and user_two also exist. and print clause print
<QuerySet [<Conversation: master, test>]>
How can I fix it?
my models.py:
class Conversation(core_models.TimeStampedModel):
participants = models.ManyToManyField(
"users.User", related_name="converstation", blank=True
)
def __str__(self):
usernames = []
for user in self.participants.all():
usernames.append(user.username)
return ", ".join(usernames)
def count_messages(self):
return self.messages.count()
count_messages.short_description = "메세지 수"
def count_participants(self):
return self.participants.count()
count_participants.short_description = "참가자 수"
class Message(core_models.TimeStampedModel):
message = models.TextField()
user = models.ForeignKey(
"users.User", related_name="messages", on_delete=models.CASCADE
)
conversation = models.ForeignKey(
"Conversation", related_name="messages", on_delete=models.CASCADE
)
def __str__(self):
return f"{self.user} says: {self.message}"
Your problem lies in that conversation ends up being one of two types depending on whether an error is thrown or not.
No error:
conversation = models.Conversation.objects.filter(
participants=user_one
).filter(participants=user_two)
In this case conversation is a queryset, that is all objects that match the filters you've specified.
Error:
conversation = models.Conversation.objects.create()
In this case conversation is a Conversation instance, so it will have the pk attribute.
What I think you're missing here is a call to get at the end of your query. As it stands the query will never throw the error models.Conversation.DoesNotExist
I hope that clears it up!
P.S. It's actually possible for two errors to be thrown when calling get, you can also get a MultipleObjectsReturned error. If you are absolutely positive that will never happen you don't need to handle it but I thought I should let you know

Django: TypeError: '<' not supported between instances (model objects)

I'm trying to migrate my Django project from Python 2.7/Django 1.11 to Python 3.7/Django 2.1.
I've found one issue and I want to understand its cause.
I have 3 models in my project:
class DeviceModel(models.Model):
name = models.CharField(max_length=255)
pirsh = models.CharField(max_length=255)
def __str__(self):
return self.name + " - " + self.pirsh
class Device(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
device_model = models.ForeignKey(DeviceModel, on_delete=models.CASCADE)
serial_number = models.CharField(max_length=255)
def __str__(self):
return self.device_model.name + " - " + self.device_model.pirsh + " - " \
+ self.serial_number
class DeviceTest(models.Model):
device = models.ForeignKey(Device, on_delete=models.CASCADE)
created_at = models.DateTimeField()
TEST_OK = '+'
TEST_ERROR = '-'
TEST_PENDING = '?'
TEST_RESULT_CHOICES = (
(TEST_OK, 'Success'),
(TEST_ERROR, 'Fail'),
(TEST_PENDING, 'Not checked'),
)
status = models.CharField(max_length=1, choices=TEST_RESULT_CHOICES, default=TEST_PENDING)
comment = models.TextField(blank=True, default="")
tester = models.CharField(max_length=255)
action = models.CharField(max_length=255)
def save(self, *args, **kwargs):
''' On save, update timestamps '''
if not self.created_at:
self.created_at = timezone.now()
return super(DeviceTest, self).save(*args, **kwargs)
def __str__(self):
return self.device_id.device_model.name + " - " + \
self.device_id.device_model.pirsh + " - " + \
self.device_id.serial_number + " - " + \
str(self.created_at) + " - " + \
"Result (" + self.status + ")"
And this is my code to sort Device objects by latest test status ('dev_filter', 'field' and 'order' parameters are parsed from GET request):
if (dev_filter!="") and (dev_filter!="-1"):
device_list = Device.objects.all().filter(device_model = dev_filter)
else:
device_list = Device.objects.all()
dev_status_list = []
for dev in device_list:
try:
dev_status_list.append(DeviceTest.objects.filter(device_id=dev.pk).latest('created_at').status)
except:
dev_status_list.append("Not checked")
device_list = [device_list for (dev_status_list, device_list) in sorted(zip(dev_status_list, device_list))]
if (order == '-'):
device_list.reverse()
This code worked fine in Python 2.7/Django 1.11 but it doesn't in Python 3.7/Django 2.1
Django marks as error sorted(zip(dev_status_list, device_list)) function:
TypeError: '<' not supported between instances of 'Device' and 'Device'
I see two solutions to this problem: either use
device_list = [device_list for (dev_status_list, device_list) in sorted(zip(dev_status_list, device_list), key=lambda x: (x[0],x[1].__str__()))]
or add __lt__ method to Device model:
def __lt__(self, other):
return self.__str__() < other.__str__()
My question is - what is changed? Does this error happen because of Python upgrade or Django upgrade? What was default sorting method in Python 2.7/Django 1.11 framework for Device objects? Am I correct that it was string representation? And which of my solutions is preferred?
Python 3 introduces new ordering comparison:
The ordering comparison operators (<, <=, >=, >) raise a TypeError exception when the operands don’t have a meaningful natural ordering.
A simple example which prints True in Python2 and raises a TypeError in Python3
class A:
pass
print(A() < A())
The reason is because Python 3 has simplified the rules for ordering comparisons which changes the behavior of sorting lists when their contents are dictionaries.
The ordering comparison operators (<, <=, >=, >) raise a TypeError exception when the operands don’t have a meaningful natural ordering
Also there is another interesting example
Quoting the example from the mentioned in this link
Python 2.7
>>> [{'a':1}, {'b':2}] < [{'a':1}, {'b':2, 'c':3}]
True
Python 3.5
>>> [{'a':1}, {'b':2}] < [{'a':1}, {'b':2, 'c':3}]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: dict() < dict()
The problem is that the second elements in both lists have different
keys and Python doesn't know how to compare them. In earlier Python
versions this has been special cased as described here by Ned
Batchelder (the author of Python's coverage tool) but in Python 3
dictionaries have no natural sort order.
You can read more about the problem here.

Finding objects without relationship in django

I am learning Django, and want to retrieve all objects that DON'T have a relationship to the current object I am looking at.
The idea is a simple Twitter copycat.
I am trying to figure out how to implement get_non_followers.
from django.db import models
RELATIONSHIP_FOLLOWING = 1
RELATIONSHIP_BLOCKED = 2
RELATIONSHIP_STATUSES = (
(RELATIONSHIP_FOLLOWING, 'Following'),
(RELATIONSHIP_BLOCKED, 'Blocked'),
)
class UserProfile(models.Model):
name = models.CharField(max_length=200)
website = models.CharField(max_length=200)
email = models.EmailField()
relationships = models.ManyToManyField('self', through='Relationship',
symmetrical=False,
related_name='related_to')
def __unicode__ (self):
return self.name
def add_relationship(self, person, status):
relationship, created = Relationship.objects.get_or_create(
from_person=self,
to_person=person,
status=status)
return relationship
def remove_relationship(self, person, status):
Relationship.objects.filter(
from_person=self,
to_person=person,
status=status).delete()
return
def get_relationships(self, status):
return self.relationships.filter(
to_people__status=status,
to_people__from_person=self)
def get_related_to(self, status):
return self.related_to.filter(
from_people__status=status,
from_people__to_person=self)
def get_following(self):
return self.get_relationships(RELATIONSHIP_FOLLOWING)
def get_followers(self):
return self.get_related_to(RELATIONSHIP_FOLLOWING)
def get_non_followers(self):
# How to do this?
return
class Relationship(models.Model):
from_person = models.ForeignKey(UserProfile, related_name='from_people')
to_person = models.ForeignKey(UserProfile, related_name='to_people')
status = models.IntegerField(choices=RELATIONSHIP_STATUSES)
This isn't particularly glamorous, but it gives correct results (just tested):
def get_non_followers(self):
UserProfile.objects.exclude(to_people=self,
to_people__status=RELATIONSHIP_FOLLOWING).exclude(id=self.id)
In short, use exclude() to filter out all UserProfiles following the current user, which will leave the user themselves (who probably shouldn't be included) and all users not following them.
i'v been searching for a method or some way to do that for like an hour, but i found nothing.
but there is a way to do that.
you can simply use a for loop to iterate through all objects and just remove all objects that they have a special attribute value.
there is a sample code here:
all_objects = className.objects.all()
for obj in all_objects:
if obj.some_attribute == "some_value":
all_objects.remove(obj)
Solution to the implementation of get_non_followers:
def get_non_following(self):
return UserProfile.objects.exclude(to_person__from_person=self, to_person__status=RELATIONSHIP_FOLLOWING).exclude(id=self.id)
This answer was posted as an edit to the question Finding objects without relationship in django by the OP Avi Meir under CC BY-SA 3.0.
current_userprofile = current_user.get_profile()
rest_of_users = Set(UserProfile.objects.filter(user != current_userprofile))
follow_relationships = current_userprofile.relationships.filter(from_person=current_user)
followers = Set();
for follow in follow_relationships:
followers.add(follow.to_person)
non_followeres = rest_of_users.difference(followers)
Here non_followers is the list of userprofiles you desire. current_user is the user whose non_followers you are trying to find.
I haven't tested this out, but it think it should do what you want.
def get_non_followers(self):
return self.related_to.exclude(
from_people__to_person=self)

Categories

Resources