I am making a kind of inventory where the ids of the existing items are written in a text file and I only need to upload the text file to the server.
I have uploaded videos, images and TIFFs to the same server without problems, but I have no idea why it is not working now!
My model:
def inventory_file_path(instance, file_name):
name = instance.date.__str__()+'.txt'
path = concatenate_paths([inventory_folder, name])
return path
class Inventory(models.Model):
date = models.DateField('Date', null=True, blank=True)
crosses = models.ManyToManyField(Cross,verbose_name='Crosses scanned', null=True, blank=True)
file = models.FileField(upload_to=inventory_file_path, blank=True, null=True)
The form:
class InventoryForm(forms.ModelForm):
class Meta:
model = Inventory
exclude = [InventoryFields.crosses]
file = forms.FileField()
def __init__(self, *args, **kwargs):
super(InventoryForm, self).__init__(*args, **kwargs)
end_year = datetime.date.today().year + 1
self.fields[InventoryFields.date].widget = forms.SelectDateWidget(years=range(start_year, end_year))
self.file = forms.FileField()
The views:
def new_inventory(request):
if request.method == GET:
inv = Inventory()
inv.date = datetime.date.today()
form = InventoryForm(instance=inv)
if request.method == 'POST':
form = InventoryForm(request.POST, request.FILES)
if form.is_valid():
inv = form.save()
when I check the database, the inventory object is being saved and it's date is right but the file is not uploaded. further more, the upload_to method is not being called
Related
I am trying to create an eCommerce application. And for useraddress (Billing and shipping ) want something like below. Here have a model called Order and UserAddress , which is
class Order(models.Model):
cart = models.ForeignKey(Cart,on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
start_date = models.DateTimeField(auto_now_add=True)
ordered_date = models.DateTimeField()
ordered_total = models.PositiveIntegerField()
shipping_price = models.PositiveIntegerField(default=0)
ordered = models.BooleanField(default=False)
billing_address = models.ForeignKey(UserAddress,related_name='billing_address',on_delete=models.CASCADE)
shipping_address = models.ForeignKey(UserAddress,related_name='shipping_address',on_delete=models.CASCADE,default=None)
and
class UserAddress(models.Model):
BILLING = 'billing'
SHIPPING = 'shipping'
ADDRESS_TYPE = (
(BILLING , 'Billing'),
(SHIPPING, 'Shipping')
)
user = models.ForeignKey(UserCheckout,
on_delete=models.CASCADE)
name = models.CharField(max_length=50)
phone = models.CharField(max_length=21,null=True)
street_address = models.CharField(max_length=50)
home_address = models.CharField(max_length=50)
type = models.CharField(max_length=100,choices=ADDRESS_TYPE)
def __str__(self):
return self.user
def get_full_address(self):
return '{0}, {1},{2}'.format(self.name ,self.user,self.phone )
And my View is
class AddressFormView(FormView):
form_class = AddressForm
template_name = 'orders/address_select.html'
def dispatch(self, request, *args, **kwargs):
b_address, s_address = self.get_address()
if not (b_address.exists() and s_address.exists()):
messages.success(self.request, 'Please add an address before continuing')
return redirect('add_address') # redirect before checkout
return super(AddressFormView, self).dispatch(request, *args, **kwargs)
def get_address(self, *args, **kwargs):
user_checkout = self.request.session['user_checkout_id']
b_address = UserAddress.objects.filter(
type=UserAddress.BILLING, user_id=user_checkout)
s_address = UserAddress.objects.filter(
type=UserAddress.SHIPPING, user_id=user_checkout)
return b_address, s_address
def get_form(self):
form = super(AddressFormView, self).get_form()
b_address, s_address = self.get_address()
form.fields['billing_address'].queryset = b_address
form.fields['shipping_address'].queryset = s_address
return form
def form_valid(self, form, *args, **kwargs):
billing_address = form.cleaned_data['billing_address']
shipping_address = form.cleaned_data['shipping_address']
self.request.session['billing_address_id'] = billing_address.id
self.request.session['shipping_address_id'] = shipping_address.id
return super(AddressFormView, self).form_valid(form, *args, **kwargs)
def get_success_url(self):
return reverse('checkout')
And the above view used a form , which is
class AddressForm(forms.Form):
billing_address = forms.ModelChoiceField(queryset=UserAddress.objects.filter(type=UserAddress.BILLING),empty_label=None,widget=forms.RadioSelect)
shipping_address = forms.ModelChoiceField(queryset=UserAddress.objects.filter(type=UserAddress.SHIPPING),empty_label=None,widget=forms.RadioSelect)
But Now when i fetching the url http://127.0.0.1:8000/cart/address/ i have the above error. The code is form a github repo which is working correctly. But in my project i am using django Allauth package and Custom User Model, which the github project that i am following didn't use. I assume , this could be an issue , because the github repo didn't use that. So is there any hints or idea or any new way to do it.
The table order_useraddress in your database does not have the type column.
Have you tried migrating/updating the database?
python manage.py makemigrations
python manage.py migrate
I have a userprofile that captures the username and the group the user is assigned to. I want the uploaded files to be saved under the group name folder. The folders already exit at the media root, the files shoud be routed to these folder
I solved the problem by the solution given. Now the username is shown as a dropdown list on the upload page. I want only the logged it username to be shown or exclude even showing it
models.py
class uploadmeta(models.Model):
path = models.ForeignKey(Metadataform, on_delete=models.CASCADE)
user_profile = models.ForeignKey(UserProfile, on_delete=models.CASCADE, null=True, verbose_name='Username')
tar_gif = models.FileField(upload_to=nice_user_folder_upload, verbose_name="Dataset") # validators=[FileExtensionValidator(allowed_extensions=['tar', 'zip'])]
def __str__(self):
return self.request.user.username
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
Group= models.CharField(max_length=500, choices=Group_choices, default='Please Select')
def __str__(self):
return self.user.username
view.py
def uploaddata(request):
if request.user.is_authenticated:
if request.method == 'POST':
form = uploadmetaform(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('file_list')
else:
form = uploadmetaform()
return render(request, 'uploaddata.html', {
'form': form
})
else:
return render(request, 'home.html')
forms.py
class uploadmetaform(forms.ModelForm):
count = Metadataform.objects.all().latest('id').id #To know the id of latest object
data = Metadataform.objects.all().filter(id=count) #return the queryset with only latest object
path = forms.ModelChoiceField(queryset=data)
def __init__(self, *args, **kwargs):
super(uploadmetaform, self).__init__(*args, **kwargs)
count = Metadataform.objects.all().latest('id').id
data = Metadataform.objects.all().filter(id=count)
self.fields['path'] = forms.ModelChoiceField(queryset=data)
class Meta:
model = uploadmeta
fields = ['path', 'user_profile','tar_gif',]
You can use the upload_to argument in the FileField.
It accept a string representing the path where you want to store the file or you can pass in a function which let you add more details.
More info from the doc: https://docs.djangoproject.com/fr/2.2/ref/models/fields/#django.db.models.FileField.upload_to
You may need to add a foreign key form uploadmeta to UserProfile like :
user_profile = models.ForeignKey(UserProfile, on_delete=models.PROTECT)
Then you can use the following
def nice_user_folder_upload(instance, filename):
extension = filename.split(".")[-1]
return (
f"your_already_definied_folder/{instance.user_profile.group}/{file}.{extension}"
)
Then use it in uploadmeta FileField
doc = models.FileField(upload_to=nice_user_folder_upload, verbose_name="Dataset")
I am using the django-resized package to resize the image.
When I upload a PNG file using this package, the extension is changed to apng.
I don't want this extension to change..
Other image files are normally uploaded.
What should I fix it?
Background
- django==2.1.5
- django-resized==0.3.9
When use Django's default model.ImageField, the extension of png does not change.
# models.py
def upload_to(instance, filename):
return 'vip/{username}/{filename}'.format(
username=instance.whose.whose.username, filename=filename)
class VipIndex(models.Model):
whose = models.OneToOneField(Profile, on_delete=models.CASCADE, related_name='vipindex')
main_big_image = ResizedImageField(crop=['middle', 'center'], size=[500, 300], quality=50, blank=True, upload_to=upload_to)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created_at']
# forms.py
class VipMainForm(forms.ModelForm):
class Meta:
model = VipIndex
fields = (
'main_big_image',
)
def __init__(self, *args, **kwargs):
super(VipMainForm, self).__init__(*args, **kwargs)
self.fields['main_big_image'].widget.attrs = {'autocomplete': 'off', 'class': 'form-control'}
# views.py
#login_required
def profile_2(request):
if request.method == 'POST':
form_main = VipMainForm(request.POST, request.FILES)
if form_main.is_valid():
nav = form_main.save(commit=False)
nav.whose = request.user.profiles
nav.save()
return redirect('profile_2')
else:
form_main = VipMainForm()
return render(request, 'accounts/profile_2.html', {
'form_main':form_main,
})
Are there specific settings to keep the extension of the png file?
Add the following to settings.py
DJANGORESIZED_DEFAULT_FORMAT_EXTENSIONS = {'PNG': ".png"}
and it will override saving the file as .apng
Here I am trying to upload multiple files but it's not working properly.I got problem while storing the foreign key for each files selected ?
I got this error.
Cannot assign "<property object at 0x04667960>": "MoreImage.image_title" must be a "Gallery" instance.
models
class Gallery(models.Model):
image_title = models.CharField(max_length=100, blank=True, null=True)
image_date = models.DateField(blank=True, null=True)
image = models.ImageField(upload_to='gallery', default='default.png')
class MoreImage(models.Model):
image_title = models.ForeignKey(Gallery, on_delete=models.CASCADE)
images = models.ImageField(upload_to='moreimage', default='default.png')
date = models.DateTimeField(auto_now_add=True)
views
def add_more_image(request):
images = Gallery.objects.all().order_by('-date')
if request.method == 'POST':
form = MoreImageForm(request.POST or None, request.FILES or None)
if form.is_valid():
more = form.save(commit=False)
for file in request.FILES.getlist('image'):
MoreImage.objects.create(image_title=Gallery.pk, images=file)
#for field in request.FILES.keys():
#for form_file in request.FILES.getlist(field):
#img = MoreImage(image_title_id=Gallery.pk,images=form_file)
#img.save()
more.save()
messages.success(request, ' Images added.')
return redirect('admin:add_gallery')
MoreImage Form
class MoreImageForm(forms.ModelForm):
class Meta:
model = MoreImage
fields = '__all__'
First of all, you shouldn't call Gallery.pk because it's won't return anything since it's a class. It should be something like gallary_instance.pk
and I don't think gallary_instance.pk will work for you because you've set commit=False which prevent to save the object into DB.
Try this,
def add_more_image(request):
images = Gallery.objects.all().order_by('-date')
if request.method == 'POST':
form = MoreImageForm(request.POST or None, request.FILES or None)
if form.is_valid():
more = form.save() # remove commit=False
for file in request.FILES.getlist('image'):
MoreImage.objects.create(image_title=more.image_title, images=file)
messages.success(request, ' Images added.')
return redirect('admin:add_gallery')
I have a Files table with information about uploaded files in a remote directory. This is the model for that table:
class Files(models.Model):
id = models.AutoField(primary_key=True)
subjectid = models.ForeignKey('Subjects', models.DO_NOTHING, db_column='subjectid')
filetypeid = models.ForeignKey(FileTypes, models.DO_NOTHING, db_column='filetypeid')
filedescid = models.ForeignKey(FileDescription, models.DO_NOTHING, db_column='filedescid')
filepath = models.CharField(max_length=45, blank=True, null=True)
filename = models.FileField(upload_to='attachments/', blank=True, null=True)
ispublic = models.IntegerField(choices=YESNO)
extra_info = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
return self.filename.name or ''
class Meta:
managed = False
db_table = 'files'
verbose_name_plural = 'files'
I've created my own URL widget to replace the Django FileField url shown as 'Currently:' in the change_form template. The link points to a view that downloads the file. So far, so good it works but the problem is that when I try to add a new file I can select the new file with the Browse file button but when I click on Save the field filename field is empty and no file is uploaded.
class MyAdminURLFieldWidget(URLInput):
template_name = 'admin/widgets/url.html'
def __init__(self, attrs=None):
#final_attrs = {'class': 'vURLField'}
final_attrs = {'type': 'file'}
if attrs is not None:
final_attrs.update(attrs)
super(MyAdminURLFieldWidget, self).__init__(attrs=final_attrs)
def get_context(self, name, value, attrs):
context = super(MyAdminURLFieldWidget, self).get_context(name, value, attrs)
context['current_label'] = _('Currently:')
context['change_label'] = _('Change:')
context['widget']['href'] = smart_urlquote('/DownloadView/' + str(value.instance.id) + '/attachment/') if value else ''
return context
class FilesAdmin(admin.ModelAdmin):
list_display = ('id', '_animalid', '_filename', '_filedesc', 'ispublic', 'extra_info')
search_fields = ('subjectid__animalid','filename')
list_per_page = 50
def formfield_for_dbfield(self, db_field, **kwargs):
if db_field.name == 'filename':
request = kwargs.pop("request", None)
kwargs['widget'] = MyAdminURLFieldWidget
return db_field.formfield(**kwargs)
else:
return super(FilesAdmin, self).formfield_for_dbfield(db_field, **kwargs)
def _animalid(self, obj):
return obj.subjectid.animalid
def _filename(self, obj):
return obj.filename.name
def _filedesc(self, obj):
return obj.filedescid.description
Can anybody tell what I'm missing here?
Hi lost Django community,
I will answer my own question since it seems that nobody was able to realize the answer. It happens that as newbie I'm following examples I've found here and there but there is little about sub-classing the FileField associated widget. So, after diving deep into the Django code I've found the answer. In my case the problem was I derived my MyAdminURLFieldWidget from URLInput instead of the correct subclass ClearableFileInput.
You are welcome.