I have my model as this:
class Event(models.Model):
EventId = models.UUIDField(primary_key=True)
Winner = models.ForeignKey('Participant', on_delete=None)
class Participant(models.Model):
ID = models.UUIDField(primary_key=True)
Name = models.CharField()
I am trying to update an existing instance of the Event object using this in form.py
class UpdateWinner(ModelForm):
def __init__(self, *args, **kwargs):
e = kwargs.pop('e', '')
super(UpdateWinner, self).__init__(*args, **kwargs)
self.fields['Winner'] = forms.ModelChoiceField(queryset=e))
class Meta:
model = Event
fields = '__all__'
and in views.py
def update_winner(request, event_id):
if request.method == 'POST':
form = UpdateWinner(request.POST, instance=Event.objects.get(EventId=event_id))
if form.is_valid():
else:
event_par = Participant.objects.filter(some query)
form = UpdateWinner(instance=event, e=event_par)
I did check by printing the eventid, correct value is getting passed. but for some reason Winner field is causing some error with the form.is_valid() function and I am getting an error "'str' object has no attribute 'model'". Can anyone help me out here
Since you don't provide an e kwarg when handling POST requests in your view, your custom __init__ function sets e = ''. This causes the error when you go to define the queryset - that empty string has no attribute model. Try:
class UpdateWinner(ModelForm):
def __init__(self, *args, **kwargs):
e = kwargs.pop('e', None)
super(UpdateWinner, self).__init__(*args, **kwargs)
if e is not None:
self.fields['Winner'] = forms.ModelChoiceField(queryset=e))
The error comes from using that line:
e = kwargs.pop('e', '')
This means if the key e is not in kwargs return ' '. Then you use it there:
self.fields['Winner'] = forms.ModelChoiceField(queryset=e))
Which result in an empty queryset.
Related
this is my view which is createview and i've used custom form and send current user id to the form
class createToDo(CreateView):
success_url = 'home'
form_class = ToDoForm
template_name = 'home.html'
user_id = None
test = 'vaseem'
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user_id'] = self.user_id
return kwargs
def get(self, request: HttpRequest, *args: str, **kwargs) -> HttpResponse:
self.user_id = request.user.id
return super().get(request, *args, **kwargs)
this is my form
class ToDoForm(ModelForm):
todos_id = forms.CharField(widget=forms.TextInput(attrs={'value':'test'}))
title = forms.CharField(widget=forms.TextInput(attrs={'id':'title'}))
description = forms.CharField(widget=forms.Textarea(attrs=
{'id':'description','cols':30,'rows':2}))
date = forms.DateField(widget=forms.DateInput(attrs={'type':'date'}))
class Meta():
model = ToDo
fields = ('title','description','date','todos_id')
def __init__(self,user_id = None,*args, **kwargs):
self.id_data = user_id
super(ToDoForm,self).__init__(*args,**kwargs)
self.fields['todos_id']= forms.CharField(widget=forms.TextInput(attrs=
{'value':self.id_data,'style':'display:none;'}))
this is the post-data,from this data it is clear value is not none then what is the problem
Variable Value
csrfmiddlewaretoken 'QCBi8WL9GYK0LdRx1FQq7sXDNjSaKjjv8IWnLwQ63toz43uNhGtM1H8C50c54zUC'
todos_id 'None'
title 'test'
description 'testdesc'
date '2023-02-23'
this is my model which is connected to my user moodel
class ToDo(models.Model):
todos = models.ForeignKey(User,on_delete=models.CASCADE)
title = models.CharField(max_length=75,null=False)
description = models.TextField(null=False)
date = models.DateField(null=False)
done = models.BooleanField(default=False)
this is the error showing, eventhough i can see the value in the todos_id input while inspecting
IntegrityError at /createToDo
null value in column "todos_id" of relation "ToDoApp_todo" violates not-null
constraint
DETAIL: Failing row contains (21, test, testdesc, 2023-02-23, f, null).
You do not need to set the user_id value in get method, you can access it in the get_form_kwargs method like this:
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user_id'] = self.request.user.id
return kwargs
Apart from that, your form override should not work, because order of arguments and keyword arguments is not correct. Arguments will come first, then the keyword arguements. Hence it should look like this:
def __init__(self,*args, user_id = None, **kwargs):
self.id_data = user_id
super(ToDoForm,self).__init__(*args,**kwargs)
I have an form
class EntryForm(forms.ModelForm):
status = forms.ChoiceField(
choices=Maca.Status.choices,
widget=forms.RadioSelect(attrs={"class": "radio-ul"}),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
class Meta:
model = Entry
fields = ["status", "commission"]
I try to update the object with class based view
def post(self, request, *args, **kwargs):
entries = UsersProductConfig.objects.get(pk=request.POST["object_id"])
maca = EntryForm(request.POST or None, instance=entries)
if maca.is_valid():
maca.save()
return maca
But I got the following error
'EntryForm' object has no attribute 'get'
Class based views are not my strength, and I don't have your full view, but one possibility is that you do not have a get() method to check for get requests. I'm thinking something like,
def get(self, request):
maca = EntryForm()
return maca
Source: Django - 'ContactForm' object has no attribute 'get'
When I use this resources.py inside Django admin everything works fine. However, when I do it on my custom view page there is an issue that popped with the **kwargs user auto-populate.
The error must be in my view as it's not passing the **kwargs but I'm not sure how to solve it. Where should I be passing this information?
KeyError at /import/
'user'
C:\Users\winkl\tj3\venv\lib\site-packages\import_export\resources.py in import_row
self.after_import_instance(instance, new, **kwargs) …
C:\Users\winkl\tj3\portfolios\resources.py in after_import_instance
instance.created_by = kwargs['user']
resources.py
class EntryResource(resources.ModelResource):
symbol = fields.Field(
attribute="symbol",
column_name="symbol",
widget=SymbolWidget(Symbol, 'name'),
)
date = fields.Field(
attribute="date",
column_name="date",
widget=widgets.DateTimeWidget(format="%Y-%m-%d %H:%M:%S"),
)
class Meta:
model = Entry
fields = ('symbol', 'date', 'id', 'amount', 'price', 'fee', 'entry_type', 'reg_fee',)
import_order = fields
skip_unchanged = False
report_skipped = True
def after_import_instance(self, instance, new, row_number=None, **kwargs):
print(f' Kwargs: {kwargs}')
instance.created_by = kwargs['user']
def after_save_instance(self, instance, using_transactions, dry_run):
pass
view.py
#login_required
def import_data(request):
if request.method == 'POST':
trade_resource = EntryResource()
dataset = Dataset()
new_trades = request.FILES['importData']
imported_data = dataset.load(new_trades.read().decode('utf-8'),format='csv')
result = trade_resource.import_data(dataset, dry_run=True, raise_errors=True)
if result.has_errors():
messages.error(request, 'Uh oh! Something went wrong...')
else:
# Import now
trade_resource.import_data(dataset, dry_run=False)
messages.success(request, 'Your words were successfully imported')
return render(request, 'dashboard/import.html')
Obviously you are getting the error because there is no entry with key 'user' in the kwargs dict.
If you look at the source, you can see that the kwargs get passed down the call stack into after_import_instance().
In your case, at no point is there ever a user entry in the kwargs dict.
However, if you pass this value in to the import_data() call then it can be retrieved and used:
your_user = load_user() # implement this as required
result = trade_resource.import_data(dataset, dry_run=True, raise_errors=True, user=your_user)
Am having a challenge i hope you can help me over come.
Am building a django driven application for movie ticket bookings and coming up short on the forms.
When a user clicks on a particular movie, i want to render a page that has a form where the user can choose options for his/her ticket like number of tickets, seat number, date etc.
However, my form returns all movies in the database.
i want to be able to return the ONLY the movie the user has clicked on, seeing that this view already returns a particular movie clicked on by a user. How can i do this?
My current method gives me an exception error 'unicode' object has no attribute 'get'
In my forms.py i have this
class MoviePaymentsForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MoviePaymentsForm, self).__init__(*args, **kwargs)
movie = forms.ModelChoiceField(queryset=Movie.objects.get(slug=args[0]))
and in my views.py i have this
class SpecificMovieTemplateView(TemplateView):
model = Movie
template_name = 'movie.html'
def get_context_data(self, *args, **kwargs):
context = super(SpecificMovieTemplateView, self).get_context_data(**kwargs)
context['movie'] = Movie.objects.get(slug=kwargs['movieslug'])
print 'Movie ID is ==> ' + str(context['movie'].id)
context['form_movie'] = MoviePaymentsForm(kwargs['movieslug'])
return context
in my models.py i have this
class MoviePayments(TimeStampedModel):
uuid_placement = shortuuid.encode(uuid.uuid4())
short_uuid = uuid_placement[:8]
reference_id = models.CharField(max_length=8, blank=True, unique=True,
default="%s" % str(short_uuid))
movie = models.ForeignKey(Movie)
ticket = models.ForeignKey(Ticket)
quantity = models.IntegerField()
date = models.ForeignKey(MovieShowDate)
time = models.ForeignKey(MovieShowTimes)
paid_for = models.BooleanField(default=False, blank=False)
mm_transaction_id = models.CharField(max_length=100, blank=True)
I finally figured it out. Like Bogdan pointed out above, i needed to pass the slug field as an argument in the init method, and use filter on the queryset to return that particular movie like so
class MoviePaymentsForm(forms.ModelForm):
def __init__(self, slug, *args, **kwargs):
super(MoviePaymentsForm, self).__init__(*args, **kwargs)
self.fields['movie'].queryset = Movie.objects.filter(slug=slug)
The problem is you are passing the movie_slug as first parameter to the form:
context['form_movie'] = MoviePaymentsForm(kwargs['movieslug']) and first parameter to the form is the data dictionary. Modify the form like this:
class MoviePaymentsForm(forms.ModelForm):
def __init__(self, slug=None, *args, **kwargs):
super(MoviePaymentsForm, self).__init__(*args, **kwargs)
movie = forms.ModelChoiceField(queryset=Movie.objects.get(slug=slug))
Or remove the argument from the args list like: slug = args.pop(0)
I use modelformset_factory, and I use full_clean() to validate the form with unique_together=True. I wonder what is the best way to handle error in case the unique_together do not validate in order to return the error message in the template.
Please take a look to my view, and tell me if im correct the way I do it, or if there is a better approach.
model:
class Attribute(models.Model):
shapefile = models.ForeignKey(Shapefile)
name = models.CharField(max_length=255, db_index=True)
type = models.IntegerField()
width = models.IntegerField()
precision = models.IntegerField()
def __unicode__(self):
return self.name
def delete(self):
shapefile = self.shapefile
feature_selected = Feature.objectshstore.filter(shapefile=shapefile)
feature_selected.hremove('attribute_value', self.name)
super(Attribute, self).delete()
class Meta:
unique_together = (('name', 'shapefile'),)
form:
class AttributeForm(ModelForm):
def __init__(self, *args, **kwargs):
super(AttributeForm, self).__init__(*args, **kwargs)
instance = getattr(self, 'instance', None)
if instance and instance.pk:
self.fields['type'].widget.attrs['disabled'] = True
self.fields['type'].required = False
self.fields['width'].widget.attrs['readonly'] = True
self.fields['precision'].widget.attrs['readonly'] = True
def clean_type(self):
if self.instance and self.instance.pk:
return self.instance.type
else:
return self.cleaned_data['type']
type = forms.ChoiceField(choices=FIELD_TYPE)
class Meta:
model = Attribute
exclude = 'shapefile'
view:
def editFields(request, shapefile_id):
layer_selected = Shapefile.objects.get(pk=shapefile_id)
attributes_selected= Attribute.objects.filter(shapefile__pk=shapefile_id)
attributesFormset = modelformset_factory(Attribute, form=AttributeForm, extra=1, can_delete=True)
if request.POST:
formset = attributesFormset(request.POST, queryset=attributes_selected)
if formset.is_valid():
instances = formset.save(commit=False)
for instance in instances:
instance.shapefile = layer_selected
try:
instance.full_clean()
except ValidationError as e:
non_field_errors = e.message_dict[NON_FIELD_ERRORS]
print non_field_errors
formset = attributesFormset(queryset=attributes_selected)
return render_to_response("basqui/manage_layer_editFields.html", {'shapefile': layer_selected, 'formset':formset}, context_instance=RequestContext(request))
instance.save()
formset = attributesFormset(queryset=attributes_selected)
return render_to_response("basqui/manage_layer_editFields.html", {'shapefile': layer_selected, 'formset':formset}, context_instance=RequestContext(request))
The disadvantage of your approach is that you have moved the validation from the form to the view.
I had the same problem recently of validating a unique together constraint where one field is excluded from the model form. My solution was to override the model form's clean method, and query the database to check the unique together constraint. This duplicates the code that is called by full_clean, but I like it because it's explicit.
I briefly thought about overriding _get_validation_exclusions which would have been more DRY, but I decided not to rely on a private api.