how to use delete() query in django? - django

I am trying to delete one of the items of a field in the table.
For example, I want to remove the 'hadi', shown in the image, from the table.
I make query to filter and exclude instance but in final part, delete() query does not accept input such as id or variable to remove specific thing in one field.
image
models.py
class Expense(models.Model):
expenser = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
debtors = models.ManyToManyField(
CustomUser,
related_name='debtors',
)
amount = models.PositiveIntegerField()
text = models.TextField()
date = models.DateField(null=True)
time = models.TimeField(null=True)
def get_debtors(self):
return ", ".join([str(d) for d in self.debtors.all()])
def who_has_no_paid(self):
return ", ".join([str(d) for d in self.debtors.all() if str(d) != str(self.expenser)])
def debt(self):
return int(float(self.amount/self.debtors.all().count()))
def get_absolute_url(self):
return reverse('expense_detail', args=[self.id])
Now what is the query that should be used in view?

Since it is a many to many field you need to use expense_obj.debtors.remove(hadi_obj) rather than using delete().
Documentation is really good for referencing
your view could be :
def remove_hadi(request):
expense_obj = Expense.objects.get(id=some_id) #get the expense obj from where u want to remove hadi
hadi_obj = User.objects.get(name="hadi") # get user obj u want to remove eg: hadi
# use m2m query
expense_obj.debtors.remove(hadi_obj)
return response

Related

how to create a SimpleListFilter in django

I don't succeed to write a query filter.
I have 3 models: Patient, Prescription and User
I write you only what is relevant for my question
Patient:
class Patient(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
Prescription:
class Prescription(models.Model):
user = models.ForeignKey(
User,
null=True,
blank=False,
on_delete=models.DO_NOTHING
)
file_extention = models.CharField(
'file extention',
max_length=8,
null=True,
blank=True,
)
So the relation between both of models (Patient and Prescription) are through User.
in the PatientAdmin, I want to filter on the file_extension according pdf or jpg of the prescription uploaded.
I created a SimpleListFilter but impossible to find the right query.
class PrescriptionFileExtensionFilter(SimpleListFilter):
"""This filter is being used in django admin panel in
patient model."""
title = 'Prescription File Ext'
parameter_name = 'file_extention'
def lookups(self, request, model_admin):
return (
('pdf', 'PDF'),
('jpg', 'JPG'),
)
def queryset(self, request, queryset):
for user in queryset:
if self.value() == 'pdf':
return queryset.filter(user=user.user).filter
(prescription__file_extention="pdf")
if self.value() == 'jpg':
return queryset.filter(user=user.user).filter
(prescription__file_extention="jpg")
That's not working...
Do I need the for user in queryset:
need What could be the query to bring me all the users with a prescription with file_extension = "pdf" (or "jpg")
You are trying to get a key from the prescription object in print(mydict['file_extention']) which I believe is causing the issue - you would instead access that property via mydict.file_extention - though I should add that mydict is not an accurate variable name for a model object as it isn't a dictionary. I don't think that for loop is actually doing anything other than printing a particular value so it can be removed altogether.
As an aside, you have two filters on your queryset, this can just be expressed as a single filter, separate by a comma, e.g.
return queryset.filter(user=user.user, prescription__file_extention="pdf")
You are also calling user.user, presumably you just want to get the user model which is kept in request.user - is that what your for loop was trying to do?
Edit
If you want to get all of the users but just filtered by JPG or PDF then you need to remove two things:
The for-loop of for user in queryset
The filter of .filter(user=user.user)
The for loop is unnecessary in the queryset function and the filter is just getting a single user, but you want to get all of them - correct?

How can I join three Django Models to return a queryset?

I want to create a queryset that references three related models, and allows me to filter. The SQL might look like this:
SELECT th.id, th.customer, ft.filename, fva.path
FROM TransactionHistory th
LEFT JOIN FileTrack ft
ON th.InboundFileTrackID = ft.id
LEFT JOIN FileViewArchive fva
ON fva.FileTrackId = ft.id
WHERE th.customer = 'ACME, Inc.'
-- AND ft.filename like '%storage%' --currently don't need to do this, but seeing placeholder logic would be nice
I have three models in Django, shown below. It's a bit tricky, because the TransactionHistory model has two foreign keys to the same model (FileTrack). And FileViewArchive has a foreign key to FileTrack.
class FileTrack(models.Model):
id = models.BigIntegerField(db_column="id", primary_key=True)
filename = models.CharField(db_column="filename", max_length=128)
class Meta:
managed = False
db_table = "FileTrack"
class TransactionHistory(models.Model):
id = models.BigIntegerField(db_column="id", primary_key=True)
customer = models.CharField(db_column="Customer", max_length=128)
inbound_file_track = models.ForeignKey(
FileTrack,
db_column="InboundFileTrackId",
related_name="inbound_file_track_id",
on_delete=models.DO_NOTHING,
null=True,
)
outbound_file_track = models.ForeignKey(
FileTrack,
db_column="OutboundFileTrackId",
related_name="outbound_file_track_id",
on_delete=models.DO_NOTHING,
null=True,
)
class Meta:
managed = False
db_table = "TransactionHistory"
class FileViewArchive(models.Model):
id = models.BigIntegerField(db_column="id", primary_key=True)
file_track = models.ForeignKey(
FileTrack,
db_column="FileTrackId",
related_name="file_track_id",
on_delete=models.DO_NOTHING,
null=True,
)
path = models.CharField(db_column="Path", max_length=256)
class Meta:
managed = False
db_table = "FileViewArchive"
One thing I tried:
qs1 = TransactionHistory.objects.select_related('inbound_file_track').filter(customer='ACME, Inc.')
qs2 = FileViewArchive.objects.select_related('file_track').all()
qs = qs1 & qs2 # doesn't work b/c they are different base models
And this idea to use chain doesn't work either because it's sending two separate queries an I'm not altogether sure if/how it's merging them. I'm looking for a single query in order to be more performant. Also it returns an iterable, so I'm not sure I can use this in my view (Django Rest Framework). Lastly x below returns a TransactionHistory object, so I can't even access the fields from the other two models.
from itertools import chain
c = chain(qs1 | qs2) # great that his this lazy and doesn't evaluate until used!
type(c) # this returns <class 'itertools.chain'> and it doesn't consolidate
x = list(c)[0] # runs two separate queries
type(x) # a TransactionHistory object -> so no access to the Filetrack or FileViewArchive fields
Any ideas how I can join three models together? Something like this?:
qs = TransactionHistory.objects.select_related('inbound_file_track').select_related('file_track').filter(customer='ACME, Inc.', file_track__filename__contains='storage')
More info: this is part of a view that will look like below. It returns a querysets that is used as part of a Django Rest Framework view.
class Transaction(generics.ListAPIView):
serializer_class = TransactionSerializer
def filter_queryset(self, queryset):
query_params = self.request.query_params.copy()
company = query_params.pop("company", [])[0]
filename = query_params.pop("filename", [])[0]
# need code here that generate filtered queryset for filename and company
# qs = TransactionHistory.objects.select_related('inbound_file_track').select_related('file_track').filter(customer='ACME, Inc.', file_track__filename__contains='storage')
return qs.order_by("id")
Based from the sql query you shared, you are filtering based on the inbound_file_track file name. So something like this should work:
TransactionHistory.objects.select_related(
'inbound_file_track',
).prefetch_related(
'inbound_file_track__file_track_id',
).filter(
customer='ACME, Inc.', inbound_file_track___filename__contains='storage',
)

How to get object using filter on ManyToManyField

Why target_dialogue is always None?
Model:
class Dialogue(models.Model):
name = models.CharField(max_length=30, blank=True)
is_conference = models.BooleanField(default=False)
participants = models.ManyToManyField(
Person,
related_name='dialogues',
)
def __str__(self):
return self.name or str(self.pk)
And in view I want to get suitable dialogue which contain in participants field 2 objects - user and companion. And if this dialogue doesn't exist I create it:
target_dialogue = None
try:
target_dialogue = Dialogue.objects.get(is_conference=False,participants__in=[user, companion])
except ObjectDoesNotExist:
target_dialogue = Dialogue()
target_dialogue.save()
target_dialogue.participants.add(user)
target_dialogue.participants.add(companion)
finally:
return render(request, 'dialogues/dialogue.html', {
'dialogue': target_dialogue,
})
But target_dialogue is always None. What's a reason of it? I was supposed to solve only a trouble in getting a dialogue from db in order to bad filter parameters, but now I have doubts about it. Maybe something else?
request.user is not a object of Person model with which you have the relation in Dialogue.
You have to first fetch the person object:
user = Person.objecs.get(user=request.user). # According to your person model
Follow same for companion and then query:
target_dialogues = Dialogue.objects.filter(is_conference=False,participants__in=[user,companion]

Simple search engine in Django. Search in html content

How to create simple search engine?
I have something like this:
def search(request):
if 'search' in request.GET:
term = request.GET['search']
if len(term) > 3:
d = Data.objects.filter(Q(content__contains=term) | Q(
desc__contains=term))
count = d.count()
return render_to_response('search_result.html', {'d': d, 'count': count}, context_instance=RequestContext(request))
return render_to_response('search_result.html', context_instance=RequestContext(request))
This is ok if I search in model but I need search in html content (I use django-chunks)
Django chunks data is stored in a model too. You can import it and filter it like any other model
class Chunk(models.Model):
"""
A Chunk is a piece of content associated
with a unique key that can be inserted into
any template with the use of a special template
tag
"""
key = models.CharField(_(u'Key'), help_text=_(u"A unique name for this chunk of content"), blank=False, max_length=255, unique=True)
content = models.TextField(_(u'Content'), blank=True)
description = models.CharField(_(u'Description'), blank=True, max_length=64, help_text=_(u"Short Description"))
class Meta:
verbose_name = _(u'chunk')
verbose_name_plural = _(u'chunks')
def __unicode__(self):
return u"%s" % (self.key,)
contains is an ok way to query if you have an extremely small dataset. It just issues a LIKE query, so it will not scale very well. If you are going to have a significant amount of data it will be a good idea to look for an engine that was created specifically for full text searching.

Issue with models/manager to organize a query

I have an application to count the number of access to an object for each website in a same database.
class SimpleHit(models.Model):
"""
Hit is the hit counter of a given object
"""
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
site = models.ForeignKey(Site)
hits_total = models.PositiveIntegerField(default=0, blank=True)
[...]
class SimpleHitManager(models.Manager):
def get_query_set(self):
print self.model._meta.fields
qset = super(SimpleHitManager, self).get_query_set()
qset = qset.filter(hits__site=settings.SITE_ID)
return qset
class SimpleHitBase(models.Model):
hits = generic.GenericRelation(SimpleHit)
objects = SimpleHitManager()
_hits = None
def _db_get_hits(self, only=None):
if self._hits == None:
try:
self._hits = self.hits.get(site=settings.SITE_ID)
except SimpleHit.DoesNotExist:
self._hits = SimpleHit()
return self._hits
#property
def hits_total(self):
return self._db_get_hits().hits_total
[...]
class Meta:
abstract = True
And I have a model like:
class Model(SimpleHitBase):
name = models.CharField(max_length=255)
url = models.CharField(max_length=255)
rss = models.CharField(max_length=255)
creation = AutoNowAddDateTimeField()
update = AutoNowDateTimeField()
So, my problem is this one: when I call Model.objects.all(), I would like to have one request for the SQL (not two). In this case: one for Model in order to have information and one for the hits in order to have the counter (hits_total). This is because I cannot call directly hits.hits_total (due to SITE_ID?). I have tried select_related, but it seems to do not work...
Question:
- How can I add column automatically like (SELECT hits.hits_total, model.* FROM [...]) to the queryset?
- Or use a functional select_related with my models?
I want this model could be plugable on all other existing model.
I have finaly find the answer, I have changed my manager and now the columns will be add to the db request.
select = {
'hits': 'hits_simplehit.hits_total',
}
qset = super(SimpleHitManager, self).get_query_set()
qset = qset.extra(select=select)
qset = qset.filter(hits_rel__site=settings.SITE_ID)
return qset
Thank you :)
Have you considered the performance impact of doing even a single database hit per object?
If you have a small amount of Objects, keep the whole table in memory and send off disk-writes as an asynchronous (background) task.