Creating unique index with peewee for table with foreign key - python

Say that I have a table called TBL_ACCOUNT which contains all of my users, and a table called TBL_EMAIL_SUBSCRIPTION where it contains the feeds that a user is subscribed to. I'm trying to make it so that there can only be one entry of each user+feed combination, so user1 can only be subscribed to feed1 once, but user1 can be subscribed to feed1 and feed2 simultaneously.
This is what my model looks like:
class TBL_ACCOUNT(BaseModel):
USERNAME = CharField(unique=True)
PASSWORD = CharField()
EMAIL = CharField(unique=True)
class TBL_EMAIL_SUBSCRIPTION(BaseModel):
USER = ForeignKeyField(TBL_ACCOUNT)
FEED = CharField()
class Meta:
indexes = (("USER_id", "FEED", True))
I have also tried just using "USER" for the indexes, but that didn't work out as the database still received duplicates.

Please refer to the peewee docs: http://docs.peewee-orm.com/en/latest/peewee/models.html#indexes-and-constraints
In your case it should look like this:
class Meta:
indexes = (
(("USER_id", "FEED"), True),
)
Note the use of commas! They are very important, because indexes are a tuple of tuples.

Related

How can i change this query to ORM?

Hi i have two models like this,
class Sample(models.Model):
name = models.CharField(max_length=256) ##
processid = models.IntegerField(default=0) #
class Process(models.Model):
sample = models.ForeignKey(Sample, blank=False, null=True, on_delete=models.SET_NULL, related_name="process_set")
end_at = models.DateTimeField(null=True, blank=True)
and I want to join Sample and Process model. Because Sample is related to process and I want to get process information with sample .
SELECT sample.id, sample.name, process.endstat
FROM sample
INNER JOIN process
ON sample.processid = process.id
AND process.endstat = 1;
(i'm using SQLite)
I used
sample_list = sample_list.filter(process_set__endstat=1))
but it returned
SELECT sample.id, sample.name
FROM sample
INNER JOIN process
ON (sample.id = process.sample_id)
AND process.endstat = 1)
This is NOT what I want.
How can i solve the problem?
This should work for you
Process.objects.filter(end_at=1).values('sample__id','sample__name','end_at')
.values() method returns selective table fields.
I'm assuming sample_list = Sample.objects.
When you are filtering a model, only the fields defined in the model are selected. In your example, id and processid. If you want to retrieve values from related models as a single record you need to use values or values_list. To get the desired query you have to do this
sample_list = sample_list.filter(process_set__endstat=1).values('id', 'name', 'process__endstat')
Btw, Django does JOIN on the foreign key field. So, you can't get ON sample.processid = process.id since processid is not a ForeignKey field.
Reference:
https://docs.djangoproject.com/en/4.0/ref/models/querysets/#values
I found JOIN not on foreign key field in django.
sample_list = sample_list.filter(processid__in=Process.objects.filter(endstat=1)
I used the medthod of
Django-queryset join without foreignkey

How to join tables with multiple foreign keys and get filtered data in Django?

I have two models like this:
class Question(models.Model):
ques_id = models.IntegerField()
test_id = models.ForeignKey('exam.Test')
ques = models.TextField()
class UserAnswer(models.Model):
user = models.ForeignKey('exam.User')
test_id = models.ForeignKey('exam.Test')
ques_id=models.ForeignKey('exam.Question')
user_ans = models.TextField()
I need to execute this query to get the correct 'ques' field values.
SELECT A.ques_id, B.ques, A.user_ans FROM useranswer A
inner join question B on B.ques_id= A.ques_id and B.test_id =A.test_id
WHERE A.user_id=1 and B.test_id='101'
So far what I have done:
UserAnswer.objects.filter(test_id=test_id, user_id=user_id).values('ques_id', 'ques_id__ques','user_ans')
But it doesn't returning the right 'ques' field values because it doesn't considering the B.test_id =A.test_id section. How to retrieve it???
First of all, your field names are misleading. Do not
suffix foreign key fields with _id! Accessing them as attributes returns model instances and django provides the _id suffixed attributes to access the actual keys implicitly:
class Question(models.Model):
test = models.ForeignKey('exam.Test')
ques = models.TextField()
# is this supposed to be the primary key? Don't do that
# ques_id = models.IntegerField()
class UserAnswer(models.Model):
user = models.ForeignKey('exam.User')
ques = models.ForeignKey('exam.Question')
user_ans = models.TextField()
# This is redundant as ques belongs to a test already
# test = models.ForeignKey('exam.Test')
I assume you want to get all the answers for one user and one test:
UserAnswer.objects.filter(
ques__test_id=test_id,
user_id=user_id
).values('ques_id', 'ques__ques', 'user_ans')

Perform lookup and update within a single Django query

I have two models: MetaModel and RelatedModel. I want to include the result of a RelatedModel lookup within a MetaModel query, and I'd like to do this within a single DB call.
I've tried to define a 'subquery' QuerySet for use in the main query, but that hasn't worked - it's still making two queries to complete the operation.
Note: I can't use a traditional ForeignKey relationship because the profile_id field is not unique. Uniqueness is a combination of profile_id and channel. This is an aggregation table and profile_id is not guaranteed to be unique across multiple third-party channels.
Any suggestions?
Models:
class Channel(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(
max_length=25,
)
class MetaModel(models.Model):
profile_id = fields.IntegerField()
channel = fields.ForeignKey(Channel))
metadata = fields.TextField()
class RelatedModel(models.Model):
related_id = fields.IntegerField()
profile_id = fields.IntegerField()
channel = fields.ForeignKey(Channel))
Dummy data
channel = Channel("Web site A")
channel.save()
sample_meta = MetaModel(profile_id=1234, channel=channel)
sample_related = RelatedModel(profile_id=1234, related_id=5678, channel=channel)
Query:
# Create a queryset to filter down to the single record we need the `profile_id` for
# I've limited to the only field we need via a `values` operation
related_qs = RelatedAccount.objects.filter(
related_id=5678,
channel=channel
).values_list("profile_id", flat=True)
# I'm doing an update_or_create as there is other data to store, not included for brevity
obj, created = MetaModel.objects.update_or_create(
profile_id=related_qs.first(), # <<< This var is the dynamic part of the query
channel=channel,
defaults={"metadata": "Metadata is added to a new or existing record."}
)
Regarding your note on uniqueness, you can use unique_together option in Django as described here in the documentation.
class MetaModel(models.Model):
profile_id = fields.ForeignKey(RelatedModel)
channel = fields.ForeignKey(Channel)
metadata = fields.TextField()
class Meta:
unique_together = ('profile_id', 'channel')
Then you can change your query accordingly and should solve your problem.

Database error: Lookup type 'in' can't be negated

I am using Django framework, appengine database.
My code for model is:
class Group(models.Model):
name = models.CharField(max_length=200)
ispublic = models.BooleanField()
logo = models.CharField(max_length=200)
description = models.CharField(max_length=200)
groupwebsite = models.CharField(max_length=200)
owner = models.ForeignKey('profile')
class Group_members(models.Model):
profile = models.CharField(max_length=200)
group = models.ForeignKey('group')
I am querying on Group_members to remove group. My query is as follows:
groups = Group_members.objects.filter(Q(profile=profile.id),~Q(group__in=group_id)
INFO:
group_id = ['128','52']
group is a foreign key to group model
My problem is when I run this query, it throws Database error: Lookup type 'in' can't be negated.
I have also performed query using __in it worked fine but does not work for foreign key.
Thanks in advance
I think you trying to filter profile id and remove groups in group_id in single filter
groups = Group_members.objects.filter(Q(profile=profile.id),~Q(group__in=group_id)
instead try this:
1)first filter the profiles form group_member :
groups = Group_members.objects.filter(profile=profile.id)
2)remove the groups form Queryset by:
groupId = [x.group.id for x in groups if x.group.id not in group_id]
Hope this will give you perfect result
2 suggestions.
Use ~Q(group__ pk__in=group_id)
Instead of using filter and not in, use exclude and in

(Django) Cannot assign "u'1'": "StaffProfile.user" must be a "User" instance

I have a model like below:
class StaffProfile(models.Model):
user = models.ForeignKey(User)
maas = models.FloatField()
maas_gunu = models.CharField(max_length=5)
When I try to insert data with a code like below:
staffprofilesay = StaffProfile.objects.filter(user = user_id).count()
if staffprofilesay > 0:
staffprofile = StaffProfile.objects.get(user = user_id)
else:
staffprofile = StaffProfile()
staffprofile.user = user_id
staffprofile.maas = calisan_formu.cleaned_data["maas"]
staffprofile.maas_gunu = calisan_formu.cleaned_data["maas_gunu"]
staffprofile.save()
I get an error like this:
Cannot assign "u'1'": "StaffProfile.user" must be a "User" instance.
What am I supposed to do?
PS: I'm using Django's User model
You need to assign a User object e.g.
from django.contrib.auth.models import User
user = User.objects.get(id=user_id)
staffprofile.user = user
user needs to be an instance of the User model, not a unicode object (which is what you are passing it).
Yes you have to pass User instance in staffprofile.user = user_id user id place.
As #david-s pointed out in a comment, if you don't have a user instance, you have to fetch from DB with an additional query.
Instead you can directly do is
staffprofile.user_id = user_id because Django behind the scene append _id in table for foreign keys so staffprofile.user will end staffprofile.user_id

Categories

Resources