Django Haystack return related insances - django-haystack

Hi I´m using django with haystack search. I have one model for Events. Thats the model I'm doing the search on. I have a second model to count the hits/views for the Events. I wan't to return the number of hits for every event additional to the search results.
my view:
def event_search(request):
if request.method == 'POST':
query = str(request.POST['search'])
events = SearchQuerySet().auto_query(query).models(Event).order_by('date')
return render_to_response('event_search.html', {"events": events}, context_instance=RequestContext(request))
else:
return render_to_response('event_search.html', context_instance=RequestContext(request))
my models:
class Event(models.Model):
name = models.CharField(max_length = 70)
date = models.DateTimeField()
description = models.TextField()
active = models.BooleanField(default=True, editable=False)
featured = models.BooleanField(default=False)
class EventHitcount(models.Model):
hit = models.ForeignKey(Event)
ip = models.CharField(max_length=40)
session = models.CharField(max_length=40)
created = models.DateTimeField(default=datetime.datetime.now())

By giving the ForeignKey field a related name it can call and count the related objects.
class Foo(models.Model):
fk = models.ForeignKey(Event,related_name='foofk')
some more fields...
In the template:
{{ foo.foofk.count }}

Related

when i update/edit data is duplicated instead of being updated in django

data is duplicated instead of being updated in django, please help me to overcome this i also tried update method but issues i have faced is image not displayed, therefore i is used save method which will save and make copy of anthor object which i dont want. it should update the same object.
views.py
def EuAdmin(request, pk):
pi = EmailDb.objects.get(id=pk)
if request.method == 'POST':
institution = request.POST.get('institution', '')
fullname = request.POST.get('fullname', '')
email = request.POST.get('email', '')
contact = request.POST.get('contact', '')
position = request.POST.get('position', '')
uploadd = request.FILES.get('upload', '')
sdata = EmailDb(institution=institution, fullname=fullname, contact=contact, email=email, position=position, uploaddata=uploadd)
sdata.save()
return HttpResponseRedirect("/eadmin")
return render(request, 'NEC/eupdate.html', {'pi': pi})
models.py
class EmailDb(models.Model):
institution = models.CharField(max_length=300, blank=True, null=True)
fullname = models.CharField(max_length=50, blank=True, null=True)
contact = models.IntegerField()
email = models.CharField(max_length=300, blank=True, null=True)
position = models.CharField(max_length=100, blank=True, null=True)
uploaddata = models.FileField(upload_to='appointment_letter')
def __str__(self):
return self.fullname
That's because you create a new EmailDb object. You can edit the one with:
from django.shortcuts import get_object_or_404
def EuAdmin(request, pk):
pi = get_object_or_404(EmailDb, pk=pk)
if request.method == 'POST':
institution = request.POST.get('institution', '')
fullname = request.POST.get('fullname', '')
email = request.POST.get('email', '')
contact = request.POST.get('contact', '')
position = request.POST.get('position', '')
uploaded = request.FILES.get('upload', '')
pi.institution = institution
pi.fullname = fullname
pi.contact = contact
pi.email = email
pi.position = position
pi.uploaddata = uploaded
pi.save()
return HttpResponseRedirect('/eadmin')
return render(request, 'NEC/eupdate.html', {'pi': pi})
Note: It is better to use a Form [Django-doc]
than to perform manual validation and cleaning of the data. A Form will not
only simplify rendering a form in HTML, but it also makes it more convenient
to validate the input, and clean the data to a more convenient type.
Note: Models normally have no Db suffix. A model is not a table, it is stored in a relational database as a table, but even then it has extra logic like validators, managers, etc.
Note: Please use an EmailField [Django-doc] instead of a CharField [Django-doc] to store an email address, this can do validation to check if the entered data is indeed an email address.
Note: It is often better to use get_object_or_404(…) [Django-doc],
then to use .get(…) [Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using
.get(…) will result in a HTTP 500 Server Error.
sdata = EmailDb(institution=institution, fullname=fullname, contact=contact, email=email, position=position, uploaddata=uploadd)
sdata.save()
This performs an INSERT SQL statement.
Since you already have object just set the value and call save() as
def EuAdmin(request, pk):
pi = EmailDb.objects.get(id=pk)
if request.method == 'POST':
institution = request.POST.get('institution', '')
fullname = request.POST.get('fullname', '')
email = request.POST.get('email', '')
contact = request.POST.get('contact', '')
position = request.POST.get('position', '')
uploaded = request.FILES.get('upload', '')
pi.institution = institution
pi.fullname = fullname
pi.contact = contact
pi.email = email
pi.position = position
pi.uploaddata = uploaded
pi.save()
return HttpResponseRedirect("/eadmin")
return render(request, 'NEC/eupdate.html', {'pi': pi})

How can i limit the number of objects we can save by with a condition and without a condition in django?

What is meant is, I want to save only one object with is_featured field true, if user tried to save another object with is_featured field true it needs to give a prompt, How can i accomplish that in django any idea?
class Event(BaseModel):
title = models.CharField(max_length=200)
time = models.TimeField()
date = models.DateField()
location = models.CharField(max_length=200)
location_url = models.URLField()
description = models.TextField()
is_featured = models.BooleanField(default=False)
image = VersatileImageField('Image', upload_to="web/events")
class Meta:
db_table = 'web_event'
verbose_name = ('Event')
verbose_name_plural = ('Event')
ordering = ('auto_id',)
def __str__(self):
return str(self.title)
You can add a check that if event is already created with is_featured true then you can return error else you can create instance
if Event.objects.filter(is_featured=True).exists():
return Response({"error":"Featured Event Already Exists"})
else:
Event.objects.create(**data)
```

update a field in all records of a table through a single form Django 4

I have the following model 'ARTICULO', which I have created and templates to edit it individually
# MODEL
class Articulo(models.Model):
id = models.AutoField(primary_key=True, verbose_name='codigo')
nombre = models.CharField(max_length=100, verbose_name='nombre elemento')
cantidad = models.PositiveSmallIntegerField(verbose_name='cantidad total')
cantidad_disponible = models.PositiveSmallIntegerField(verbose_name='cantidad disponible', default=5)
UNIDAD = 'und'
KILO = 'kg'
LITRO = 'L'
UNIDADES_BASE = [
(UNIDAD, 'unidades'),
(KILO, 'Kilogramos'),
(LITRO, 'litros'),
]
unidades = models.CharField(max_length=3, choices=UNIDADES_BASE, default=UNIDAD, verbose_name='unidad base')
area = models.CharField(max_length=100, verbose_name='tipo inventario', default='primaria')
persona_asignada = models.CharField(max_length=100, default='almacen', verbose_name='persona asignada')
def __str__(self):
trama = "articulo: " + self.nombre
return trama
#form to edit individually
class ArticuloEditarForm(forms.ModelForm):
class Meta:
model = Articulo
fields = ['nombre', 'cantidad', 'unidades']
# view for generate form of individual article
def editar(request, id):
articulo = Articulo.objects.get(id=id)
formulario = ArticuloEditarForm(request.POST or None, instance=articulo)
if formulario.is_valid() and request.POST:
formulario.save()
return redirect('inventario_inicio')
return render(request, 'inventario/editar.html', {'formulario': formulario})
but additionally I would like to create a page where I can perform an update of all the records of the table as a whole (as in the following image)
When clicking on the button, all records with the checkbox activated are updated in the database according to the value indicated in their text box.
From what I have investigated so far, I think I understand that I should use the form.Form class and not form.ModelForm in combination with formsets, but in the attempts I have made, I tried trying to define a form in this way, but it does not work for me.
class AsignarReservasArticulos(forms.Form):
articulos = Articulo.objects.all()
for x in articulos:
print(x)
participa = forms.BooleanField(label='')
My deduction tells me that I must generate the form that I show in my image in an integral way from my FORM or I must make a part in the form and another in the view.

How to retrieve all many_to_many relations for each objects in a single query

I have four tables :
class Recipe(models.Model):
item_recipe = models.OneToOneField(Item, on_delete=models.CASCADE, related_name='item_recipe')
items = models.ManyToManyField(Item, through='RecipeItem')
class RecipeItem(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
class Item(models.Model):
def __str__(self):
return self.name
name = models.CharField(max_length=200, unique=True)
effects = ArrayField(models.CharField(max_length=200), blank=True, default=list)
pods = models.IntegerField(null=True)
level = models.IntegerField(null=True)
type = models.CharField(max_length=200, null=True, blank=True, default="Ressource")
image = models.URLField()
class Prix(models.Model):
def __str__(self):
return self.item.name
prix_x1 = models.IntegerField(null=True)
prix_x10 = models.IntegerField(null=True)
prix_x100 = models.IntegerField(null=True)
saved_at = models.DateTimeField()
item = models.ForeignKey(Item, on_delete=models.CASCADE)
A recipe is composed of 1 to 8 Items with a certain quantity indicated is the RecipeItem table.
I would like a query that gives me the price of every Recipe.
In other word, a query that get all items and its prices for every recipe and sum it.
I don't find a way to do that without a for loop.
EDIT
Here is what i have currently, it's not pretty and not effective ..
items = Recipe.objects.all().select_related('item').annotate(
prix1_ressource=Subquery(
Prix.objects.filter(
item=OuterRef('items')
).values('prix_x1').exclude(prix_x1__isnull=True).order_by('-saved_at')[:1]
),
prix1_item=Subquery(
Prix.objects.filter(
item=OuterRef('item_recipe')
).values('prix_x1').exclude(prix_x1__isnull=True).order_by('-saved_at')[:1]
)
).exclude(prix1_item__isnull=True).values('id', 'item_recipe__name', 'prix1_ressource', 'items__name',
'recipeitem__quantity', 'prix1_item',
'item_recipe__type', 'item_recipe')
for id in np.unique(items.values_list('id', flat=True)):
item = items.filter(id=id)
try:
prix_craft = sum([i['recipeitem__quantity'] * i['prix1_ressource'] for i in item])
gain = item[0]['prix1_item'] - prix_craft
except TypeError:
continue
There is really not a nice SQL way. At some point either you or Django will have to iterate over all the items in a query and sum them. Perhaps you could make it a little more efficient by using an Inner join, as documented here, using it to preload the items. But resolving the item's current Prix might require a separate query each time.

How can I join two child tables using Django Querset API?

I have a model with two child tables and one parent table. Here is the sample model classes.
# Stores list of unique category names
class Category(models.Model):
category = models.CharField(max_length=20, unique=True, validators=[MinLengthValidator(limit_value=5)])
name = models.CharField(max_length=20, validators=[MinLengthValidator(limit_value=8)])
# Parent class for the next two child classes
class DailyLog(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
name = models.CharField(max_length=100, validators=[MinLengthValidator(limit_value=8)])
code = models.CharField(max_length=4, validators=[MinLengthValidator(limit_value=3)])
suggested_values = models.CharField(max_length=100, null=True, blank=True)
# First child class defines display order for dailylog items
class DailyLogDisplayOrder(models.Model):
category_item = models.ForeignKey(DailyLog, on_delete=models.CASCADE)
display_order = models.PositiveIntegerField()
# Second Child class publishes dailylog on a daily bases
class DailyLogCheckList(models.Model):
daily_task = models.ForeignKey(DailyLog, on_delete=models.CASCADE)
publish_date = models.DateField(auto_now=True)
daily_task = DailyTaskCategoryManager() # Log manager to get records per category
How do I perform a cartesian product query? The last column comes from the first child table Dailylogdisplayorder. Here is the raw sql.
select daily_task_id, checklist.publish_date, disporder.display_order
from dailylogchecklist checklist, compliance_dailylogdisplayorder disporder
where checklist.daily_task_id = disporder.category_item_id and checklist.publish_date='2020-07-12'
I have tried using cursor.execute() method per Django documentation. However, I am not able to figure out how to return results in QuyerySet. And also looking for a better way to combine child columns using QuerySet. The return queryset is assigned to a formset.
class DailyTaskCategoryManager(models.Manager):
def with_displayorder(self, user):
from django.db import connection
dtrange = datetime.today().date()
with connection.cursor() as cursor:
cursor.execute("select daily_task_id, checklist.publish_date, disporder.display_order
from dailylogchecklist checklist, compliance_dailylogdisplayorder disporder
where checklist.daily_task_id = disporder.category_item_id and
checklist.publish_date=%s", [dtrange])
result_list = []
for row in cursor.fetchall():
p = self.model(id=row[0], daily_task_id=row[1], publish_date=row[2])
p.display_order = row[3]
result_list.append(p)
return result_list
I already answered to a similar question, You can use prefetch_related() to get the related child table data. Check this answer
https://stackoverflow.com/a/71571509/9561654

Resources