I am trying to update search vector field using post_save signal. Through “Admin.py”, It is working perfectly, but through “Form page” , the searchVector field or any other field is not getting updated. In form page, I have many to many field – “Tag” that I save through “form.save_m2m” method Please review my code and suggest .. https://dpaste.org/ujPi Thanks in advance
#models.py class JobPostManager(models.Manager): def search(self, search_text): search_vectors = ( SearchVector( 'job_title', weight='A', config='english' ) ) search_query = SearchQuery( search_text, config='english' ) search_rank = SearchRank(search_vectors, search_query) trigram_similarity = TrigramSimilarity( 'job_title', search_text ) qs = ( self.get_queryset() .filter(search_vector=search_query) .annotate(rank=search_rank + trigram_similarity) .order_by('-rank') ) return qs class JobPost(models.Model): job_title = models.CharField(max_length=100, db_index=True) job_description = models.TextField() tags = TaggableManager() author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True) company_name = models.CharField(max_length=100,blank=True,null=True, db_index=True) objects = JobPostManager() def __str__(self): return self.job_title def get_absolute_url(self): return reverse('job_post_detail', kwargs={'slug': self.slug, 'pk':self.pk}) #################################################################################### #################################################################################### # views.py class JobPostCreateView(LoginRequiredMixin, CreateView): model = JobPost fields = ['job_title','job_description','tags'] widgets = { 'tags' : forms.TextInput(attrs={'data-role':'tagsinput'}), } def get_form(self): form = super().get_form() form.fields['tags'].widget = forms.TextInput(attrs={'value': 'all'}) return form def form_valid(self, form): print("views - form valid - run ") newpost = form.save(commit=False) form.instance.author = self.request.user form.instance.company_name = self.request.user.company_name print("form---------------------------") print(form.instance.author) print(form.instance.job_title) print(form.instance.company_name) print("form end---------------------------") newpost.save() print('newpost') print('--------------------------------',newpost) print('newpost',newpost.author) print('newpost',newpost.job_title) print('Search VECTOR') print('-------------------') print(newpost.search_vector) print('Search VECTOR') form.save_m2m() print('save_m2m-----------------------') print('form-------------',form) print('form end-------------------') return super().form_valid(form) ########################################################################### ########################################################################### from django.db.models.signals import post_save from django.dispatch import receiver from .models import JobPost @receiver(post_save, sender=JobPost) def create_profile(sender, instance, created, **kwargs): if created: # JobPost.objects.update(search_vector="instance") print("i am inside --------------signal") print(instance.job_title) print(instance.job_description) print(instance.tags) print(instance.company_name) print(instance.author) print('Search VECTOR') print('-------------------') print(instance.search_vector) print('Search VECTOR') print("i am inside signal") print("i am inside signal") print("Signal end --------------------------------------") print("run filter --------------------------------------") p = JobPost.objects.filter(pk=instance.pk) print(p) p2 = JobPost.objects.get(pk=instance.pk).search_vector print(p2) print(JobPost.objects.filter(pk=instance.pk)[0].job_title) print("run filter end--------------------------------------") p.update(search_vector="instance") JobPost.objects.filter(pk=instance.pk).update(job_title="Java developer") print('Search VECTOR after update ') print('-------------------') print(instance.search_vector) print('Search VECTOR') ########################################################################### ############################################################################ ## Form HTML <div class="row"> <div class="col-25"> <label class="fr" for="{{ form.job_title.id_for_label }}">Job title *:</label> </div> <div class="col-75"> {{ form.job_title }} </div> <div class="invalid-tooltip"> {{ form.job_title.errors }} </div> </div> <div class="row"> <div class="col-25"> <label class="fr" for="{{ form.job_description.id_for_label }}">Job description *:</label> </div> <div class="col-75"> {{ form.job_description }} </div> <div class="invalid-tooltip"> {{ form.job_description.errors }} </div> </div> #############################################################
Advertisement
Answer
Just to be absolutely sure, everything is saving perfectly but your signals are not being called, right?
This is solvable by adding 2 lines of code inside the apps.py
file (which should live at the same depth as your models.py
file). For example, if the application (or the folder containing models.py
) is called “jobs” and create_profile
is inside the file named signals.py
you should modify the apps.py
file like this:
from django.apps import AppConfig from django.utils.translation import ugettext_lazy as _ class JobsConfig(AppConfig): name = 'jobs' verbose_name = _('Jobs') # THE FOLLOWING SHOULD BE ADDED. def ready(self): from . import signals # noqa
Django only finds some files “magically” when it expects their names (like models.py
, management/commands
, etc) but not the signals.py
(or the name of the file where create_profile
exists). The fix in the snippet is not “pretty”, but you should do the import inside the ready
method as django might call signals.py
twice if it is imported somewhere else.
PD. If this works for you, please let me know if you get a “Joined field references are not permitted in this query” error when saving (the reason I found this question) is because Django-Taggit + SearchVector inside the same model raises this error