I have a question. Can i pass the data for filtering another field(manytomany) in admin.py ? I need to get linked foreignkey id value.
Models.py
class Pansions(models.Model):
......
category = models.ForeignKey(Category, null=True, on_delete=models.PROTECT, related_name='cards', verbose_name='Category')
......
Admin.py
class PansionatAdmin(admin.ModelAdmin):
.....
fields = ('title', 'slug', 'category', 'tags')
....
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "tags":
kwargs["queryset"] = Tag.objects.filter(category__id = "GET ID FOREIGNKEY_FIELD (caterogy)")
return super().formfield_for_manytomany(db_field, request, **kwargs)
I try to get data from models.py, but it not happen. Is it possible?
Here’s an answer to a similar question that should do the trick: https://stackoverflow.com/a/61579287/9638991. For your use case it would look like this (untested code):
class PansionatAdmin(admin.ModelAdmin):
.....
fields = ('title', 'slug', 'category', 'tags')
....
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "tags" and hasattr(request, ‘pansion_obj’):
kwargs["queryset"] = Tag.objects.filter(category=request.pansion_obj.category)
return super().formfield_for_manytomany(db_field, request, **kwargs)
def get_object(self, request, object_id, from_field=None):
obj = super().get_object(request, object_id, from_field=from_field)
# Cache object for use in formfield_for_manytomany
request.pansion_obj = obj
return obj
Related
I have a model which has a field 'keywords'. When I use a form to create/modify records, I am able to clean this field and then save it.
class ILProjectForm(forms.ModelForm):
class Meta:
models = ILProject
fields = '__all__'
def clean_keywords(self):
k = self.cleaned_data.get('keywords')
if k:
k = ','.join([a.strip() for a in re.sub('\\s+', ' ', k).strip().split(',')])
return k
However, I am not sure how to run clean() to update the data when I am using the list_editable option in the admin page.
I tried something like this bit I get an error saying I cannot set an attribute. What is the correct way to update the data after it has been cleaned?
class MyAdminFormSet(BaseModelFormSet):
def clean(self):
print(type(self.cleaned_data))
recs = []
for r in self.cleaned_data:
if r['keywords']:
r['keywords'] = ','.join([a.strip() for a in re.sub('\\s+', ' ', r['keywords']).strip().split(',')])
print(r['keywords'])
recs.append(r)
self.cleaned_data = recs <-- this part is problematic.
class ILProjectAdmin(...)
...
def get_changelist_formset(self, request, **kwargs):
kwargs['formset'] = MyAdminFormSet
return super().get_changelist_formset(request, **kwargs)
It should be like this:
class ILProjectAdmin(...)
...
def get_changelist_form(self, request, **kwargs):
return ILProjectForm
Please refer this tip: Django: Access request object from admin's form.clean()
class ProjectRequestForm(forms.ModelForm):
class Meta:
model = ProjectRequest
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(ProjectRequestForm, self).__init__(*args, **kwargs)
def clean(self):
if self.request.user.has_perm('access_role'):
raise ValidationError(f'No permission', code='invalid')
class ProjectRequestAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super(ProjectRequestAdmin, self).get_form(request, obj, **kwargs)
class AdminFormWithRequest(form):
def __new__(cls, *args, **kwargs):
kwargs['request'] = request
return form(*args, **kwargs)
return AdminFormWithRequest
def get_changelist_form(self, request, **kwargs):
class AdminFormWithRequest(ProjectRequestForm):
def __new__(cls, *args, **kwargs):
kwargs['request'] = request
return ProjectRequestForm(*args, **kwargs)
return AdminFormWithRequest
I need return only current user on add/change admin model field:
In my admin/model the field fk user, return a list of users, independent if the current user is_admin or not:
How put initial value only current user, and nothing more.
admin.py
class AdminProductModel(admin.ModelAdmin):
inlines = [AdminProductImages,AdminProductFeatures]
model = Product
def formfield_for_dbfield(self, db_field, request, **kwargs):
formfield = super(AdminProductModel, self).formfield_for_dbfield(
db_field, request, **kwargs)
if db_field.name == 'user':
formfield.widget.can_add_related = False
formfield.widget.can_change_related = False
return formfield
def product_thumb(self, obj):
# return HTML link that will not be escaped
return mark_safe(
'<img src="%s" style="width:30px;height:30px;">' % (ProductImages.objects.filter(product=obj).first().image_file_w200_png.url)
)
product_thumb.short_description = 'Preview'
list_display = ['product_thumb','user','slug','created_at']
list_display_links = ('slug','product_thumb')
exclude = ['slug','product_title_seo']
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.filter(user_id=request.user)
models.py
class Product(models.Model):
user = models.ForeignKey(User,verbose_name = u'usuário', on_delete=models.CASCADE)
#...otherfields
I literally searched similar questions but didn't a answer that solves my question
I want a functionality like a question can have multiple answers
my models.py
class QuestionModel(models.Model):
question = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
doubt_class_id = models.ForeignKey(DoubtClasses, on_delete=models.CASCADE)
conceptual_class_id = models.ForeignKey(LiveClass_details, on_delete=models.CASCADE, null=True, blank=True)
status = models.BooleanField(default=False)
mentor = models.ForeignKey(Mentor, on_delete=models.CASCADE, null=True, blank=True)
def __str__(self):
return self.question
def clean(self):
if self.doubt_class_id and self.conceptual_class_id :
raise ValidationError("only one field can be set")
class AnswersModel(models.Model):
answer = models.TextField()
question_id = models.ForeignKey(QuestionModel, on_delete=models.CASCADE)
my urls.py
path('questions/', views.QuestionModelView.as_view()),
path('questions/<int:id>/', views.QuestionModelViewID.as_view()),
path('questions/<int:id>/answer/', views.AnswerModel.as_view()),
my views.py
# Create your views here.
class QuestionModelView(mixins.ListModelMixin, mixins.CreateModelMixin,GenericAPIView):
queryset = models.QuestionModel.objects.all()
serializer_class = serializers.QuestionModel_serializer
permission_classes = [IsAuthenticated]
def get(self, request):
return self.list(request)
def post(self, request):
return self.create(request)
class QuestionModelViewID(mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin,GenericAPIView):
queryset = models.QuestionModel.objects.all()
serializer_class = serializers.QuestionModel_serializer
permission_classes = [IsAuthenticated]
lookup_field = 'id'
def get(self, request, id=None):
if id:
return self.retrieve(request, id)
else:
return Response(status=status.HTTP_204_NO_CONTENT)
def put(self, request, id=None):
if int(request.POST.get('author')) != self.request.user.id:
return Response("you cannot edit othe user question", status=status.HTTP_405_METHOD_NOT_ALLOWED)
if id:
return self.update(request, id)
else:
return Response(status=status.HTTP_204_NO_CONTENT)
def delete(self, request, id=None):
if int(request.POST.get('author')) != self.request.user.id:
return Response("you cannot destroy othe user question", status=status.HTTP_405_METHOD_NOT_ALLOWED)
if id:
return self.delete(request, id)
else:
return Response(status=status.HTTP_204_NO_CONTENT)
class AnswerModel(mixins.ListModelMixin, mixins.CreateModelMixin, GenericAPIView):
lookup_field = 'id'
serializer_class = serializers.AnswerModel_serializer
def get_queryset(self, *args, **kwargs):
return models.AnswersModel.objects.filter(question_id = self.kwargs['id'])
def get(self, request, id=None):
return self.list(request)
def post(self, request, id=None):
if request.user.is_superuser:
return self.create(request, id)
else:
return Response("only superuser can post a answer", status=status.HTTP_400_BAD_REQUEST)
I want to make a url like questions/id/answers/answer_id where id is the question id and answer_id is the id for a particular answer as a question can have multiple answers but for that i want to add 2 lookup_fields in my view which i am not getting how to add it or please suggest another approach for this query if its not possible to do like that
if you have query like this questions/id/answers/answer_id
you can do like this if I understood your question good.
def get_queryset(self):
id = self.kwargs['id']
answerid = self.kwargs['answer_id']
queryset = Model.objects.get(
id=id,answerid=answerid)
return queryset
or
def get(self, request, id, answer_id):
Questiomn = Model.objects.get(
id=id,answerid=answerid)
I am trying to use CreateView and UpdateView to modify records. My problem is that the ForeignKey dropdown lists values (Psa.number) for all companies instead only those of the company to which the user belongs.
class Psa(models.Model):
owner = models.ForeignKey(Employer)
number = models.PositiveIntegerField(unique=True...
type = models.CharField(max_length=6 ...
class Employer(models.Model):
employer_name = models.CharField(max_length=100, unique=True)
The form:
class PsaCreateForm(forms.ModelForm):
class Meta:
model = Psa
fields = [
'number',
'type',
]
What is the best way to solve this? I've got several other conditions that use the same company foreignkey relationship so is there a way to create a method on the model that I can reuse?
You need get_form_kwargs(self) in CreateView and UpdateView:
forms.py:
class PsaCreateForm(forms.ModelForm):
model = Psa
fields = [
'number',
'type',
]
def __init__(self, *args, **kwargs):
self.current_user = kwargs.pop('user')
super(PsaCreateForm, self).__init__(*args, **kwargs)
if self.current_user:
self.fields['number'].queryset = Psa.objects.filter(owner=self.current_user)
views.py
class PsaCreate(CreateView):
model = Psa
template_name = 'form.html'
form_class = PsaCreateFrom
def get_form_kwargs(self):
kwargs = super(PsaCreate, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
Also a good idea. Set def dispatch(self, request, *args, **kwargs): in your Views.
def dispatch(self, request, *args, **kwargs):
obj = self.get_object()
if obj.owner != self.request.user:
return HttpResponseRedirect(reverse('home'))
return super(PsaUpdate, self).dispatch(request, *args, **kwargs)
I am trying to get http://areyouahuman.com/ capcha working on my site
I found
https://gist.github.com/klanestro/9572114
I subclassed it
class Turtle_Form(forms.ModelForm,AreYouHumanForm):
''' This is code to make sure the User automatically saves the
user to the database in context.
'''
def save(self, *args, **kwargs):
kwargs['commit']=False
obj = super(Turtle_Form, self).save(*args, **kwargs)
if self.request:
obj.user = self.request.user
obj.save()
return obj #<--- Return saved object to caller.
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
return super(Turtle_Form, self).__init__(*args, **kwargs)
and
class OfertoCreateForm(Turtle_Form):
class Meta:
model = Oferto
fields = ( "name",
"description",
"tags",
"time",
"requirements",
"location",
"image",
'AreYouHumanForm',
)
but nothing comes up on the form, no errors nothing.
The field in that gist is called session_secret, which is the name you should be using in the fields tuple.