File Upload in Django modelForm - django

I am trying to upload documets in appengine-django.
Docs getting uploaded successfully with pure django code [ using python manage.py runsever ].
But when i am trying to run django with appengine project it gives me error ,
[Errno 30] Read-only file system: u'/home/nishant/workspace1/problemdemo/uploaded_files/1372313114_43_nishant26062013.zip'
This error caused because Developers have read-only access to the filesystem on App Engine.
Is there is another way to upload docs to google cloud sql ?
Here is my code ,
models.py
from django.db import models
import time
# Create your models here.
def get_upload_file_name(instance,filename):
return "uploaded_files/%s_%s" % (str(time.time()).replace('.','_'),filename)
class Candidate(models.Model):
title=models.CharField(max_length=20)
resume=models.FileField(upload_to=get_upload_file_name)
def __unicode__(self):
return self.title
forms.py
from django import forms
from actualproblem.models import Candidate
class TestForm(forms.ModelForm):
class Meta:
model=Candidate
fields=('title','resume',)
views.py
# Create your views here.
from django.shortcuts import render
from actualproblem.forms import TestForm
def sampletest(request):
if request.method=='POST':
form = TestForm(request.POST,request.FILES)
if form.is_valid():
form.save()
else:
form=TestForm()
return render(request,'profile.html',{'form':form})
How can i upload documetns to google cloud sql ?

You may solve the conundrum by using Uploadcare, it can help in situations when you have little or no control over host filesystem (GAE, heroku, shared hosting or whatnot). Uploaded files will be stored in Uploadcare and you will store file UUIDs or URLs in your DB.
There is Django package: pyuploadcare
disclosure: I am one of Uploadcare developers and am posting this not to shamelessly promote the service but because it was built to solve cases like this one.

Related

Create user login and password for users from csv using ImportExport Module Django

I want to create a new user's login and random/same password using CSV file using the ImportExport module Django. I've tried many examples but for no use. Can you please suggest anything? I've even tried to make password field in the import csv file. Let me know any tutorial/link that you can share to achieve this.
If you're looking to populate the database with dummy data, there is a module called faker in python.
Here is a small code snippet showing how you can use faker:
import os
# Configure settings for project
# Need to run this before calling models from application!
os.environ.setdefault('DJANGO_SETTINGS_MODULE','(YOUR DJANGO PROJECT).settings')
import django
# Import settings
django.setup()
import random
from (YOUR DJANGO APP).models import User
from faker import Faker
fakegen = Faker()
def populate(N=5):
for entry in range(N):
# Create Fake Data for entry
fake_name = fakegen.name().split()
fake_first_name = fake_name[0]
fake_last_name = fake_name[1]
fake_email = fakegen.email()
# Create new User Entry
user = User.objects.get_or_create(first_name=fake_first_name,
last_name=fake_last_name,
email=fake_email)[0]
if __name__ == '__main__':
print("Populating the databases...")
populate(20)
print('Populating Complete')
django-import-export contains several hooks which you can use to manipulate data prior to insertion in the db. This seems like the ideal way to generate a random password for each user.
You can combine this with Django's make_random_password() function. It doesn't seem like a good idea to have passwords in the import spreadsheet, but maybe you need to do that for some reason.
You will need to create your own Resource subclass, and override the before_save_instance(), for example:
class UserResource(resources.ModelResource):
def before_save_instance(self, instance, using_transactions, dry_run):
pw = User.objects.make_random_password()
instance.set_password(pw)
class Meta:
model = User
fields = ('id', 'username', 'password')
import_id_fields = ['id']

Auto register Django auth models using custom admin site

I implemented authentication management using Django auth with the default admin site but then I wanted to use my own AdminSite to rewrite some behaviors:
class OptiAdmin(admin.AdminSite):
site_title = "Optimizer site's admin"
#...Other stuff here
Then registered my own models:
admin_site = OptiAdmin(name='opti_admin')
admin.site.register(MyModel, MyModelAdmin)
#Other stuff here
But when I go to the admin site I am only able to see the models I just registered, which sounds fair to me but I would like to see all the other apps models in this new custom site including the auth's users and groups and I don't know how to do this automatically like the default admin does, pls help :).
Create your own AdminSite with a simple __init__() override.
Import your admin in urls.py.
Replacing the Django Admin and getting the autodiscover() behavior is possible with minimal effort. Here's a project structure generated in the typical django-admin startproject project fashion:
project/
manage.py
project/
__init__.py
settings.py
urls.py
wsgi.py
admin.py # CREATE THIS FILE
project/admin.py: (I think it makes the most sense to do this at the project level.)
from django.contrib.admin import * # PART 1
class MyAdminSite(AdminSite):
site_header = "My Site"
def __init__(self, *args, **kwargs):
super(MyAdminSite, self).__init__(*args, **kwargs)
self._registry.update(site._registry) # PART 2
site = MyAdminSite()
project/urls.py (snippet):
from . import admin # PART 3
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
Part 1 is simple Python. By importing everything from django.contrib.admin into your namespace, it acts as a drop-in replacement. I suppose you don't have to do this, but it helps preserve expectations. Part 3, simply connect up your admin. Part 2 is the real trick. As the documentation says, autodiscover() is called to do the work. All autodiscover does is go through INSTALLED_APPS attempting to import a file called admin.py. Importing runs the code of course and that code is doing the same thing you do to register models (example by decorator and example by method). No magic. You don't have to register your models with your customized admin (as the documentation says).
Autodiscover looks smarter than it is with its register_to kwarg. That indicates you could call autodiscover() yourself passing your own admin. Nope; there's no wiring connected there (future feature?). The assignment happens here and is fixed to the native AdminSite instance here (or here using the decorator). Django contrib models register to that instance and so will any third-party libraries. It's not something you can hook into.
Here's the trick though, _registry is just a dictionary mapping. Let Django autodiscover all the things and then just copy the mapping. That's why self._registry.update(site._registry) works. "self" is your customized AdminSite instance, "site" is Django's instance and you can register your models with either.
(Final note: If models are missing, it's because of import order. All the registration to Django's AdminSite needs to happen before you copy _registry. Registering directly to your customized admin is probably the easiest thing.)
The Django docs suggest using SimpleAdminConfig with a custom admin site.
INSTALLED_APPS = (
...
'django.contrib.admin.apps.SimpleAdminConfig',
...
)
That prevents the models being registered with the default AdminSite.
The docs seem to assume that you will import the models individually and add them to your custom admin site:
from django.contrib.auth.models import Group, User
from django.contrib.auth.admin import GroupAdmin, UserAdmin
admin_site.register(Group, GroupAdmin)
admin_site.register(User, UserAdmin)
This would be very repetitive if you have models in many apps. It doesn't offer any advice how to automatically register models from all your apps with your custom site.
You could try monkey patching admin, and replacing admin.site with your own.
from django.contrib import admin
admin.site = OptiAdmin(name='opti_admin')
Then, when code called admin.site.register(), it would register the model with your admin site. This code would have to run before any models were registered. You could try putting it in the AppConfig for your app, and make sure that your app is above django.contrib.admin.
Adding to JCotton's great answer:
Using django 2.0, overriding site_header and site_title in the custom admin site only works for the index page.
To get it to work with all admin views, extend JCotton's code with the following:
def __init__(self, *args, **kwargs):
super(MyAdminSite, self).__init__(*args, **kwargs)
self._registry.update(site._registry) # PART 2
for model, model_admin in self._registry.items():
model_admin.admin_site = self
Just include init method in your CustomAdminSite class like this.
class CustomAdminSite(admin.AdminSite):
def __init__(self, *args, **kwargs):
super(CustomAdminSite, self).__init__(*args, **kwargs)
self._registry.update(admin.site._registry)

How to set app_label in test

I am going through online tutorial for a basic Django web page and a single app.
The first and only thing I have done so far is to create the project and a single app with the sqllite database.
I have added the app to the settings.py file correctly.
Within the app models.py I have defined a single model.
The makemigrations command has successfully created the database for the model.
After creating the model class, I attempted to write the following test script to test the constructor of the model. This script lives in the app directory at the same level as the models.py.
from django.test import TestCase
from models import Foodie # the model
import os
# Create your tests here.
class TestModel(unittest.TestCase):
def test_foodie(self):
tc = Foodie()
if __name__ == '__main__':
unittest.main()
I get the error:
builtins.IndexError: list index out of range
File "C:\WebDev\DinnerServer\Rolls\tests.py", line 2, in <module>
from models import Foodie
File "C:\WebDev\DinnerServer\Rolls\models.py", line 7, in <module>
class Foodie(models.Model):
File "C:\Python33\Lib\site-packages\Django-1.7.1-py3.3.egg\django\db\models\base.py", line 116, in >__new__
kwargs = {"app_label": package_components[app_label_index]}
(The app where the model resides is titled Rolls)
How or why is this failing and how do I set the app_label for the unit test to work?
Basic error, the import statement is wrong.
Should be... from Rolls.models
you need to add def __str__(self): to your Foodie model in models.py.
class Foodie(models.Model):
#some fields
def __str__(self):
# you access to model fiels here
return self.label
Also see the doc may help you.

Getting Google App Engine blob info in Django view

This is a follow up question for Django on Google App Engine: cannot upload images
I got part of the upload of images to GAE Blobstore working. Here's what I did:
In models.py I created a model PhotoFeature:
class PhotoFeature(models.Model):
property = models.ForeignKey(
Property,
related_name = "photo_features"
)
caption = models.CharField(
max_length = 100
)
blob_key = models.CharField(
max_length = 100
)
In admin.py I created an admin entry with an override for the rendering of the change_form to allow for insert of the correct action to the Blobstore upload url:
class PhotoFeatureAdmin(admin.ModelAdmin):
list_display = ("property", "caption")
form = PhotoFeatureForm
def render_change_form(self, request, context, *args, **kwargs):
from google.appengine.ext import blobstore
if kwargs.has_key("add"):
context['blobstore_url'] = blobstore.create_upload_url('/admin/add-photo-feature')
else:
context['blobstore_url'] = blobstore.create_upload_url('/admin/update-photo-feature')
return super(PhotoFeatureAdmin, self).render_change_form(request, context, args, kwargs)
As I use standard Django, I want to use the Django views to process the result once GAE has updated the BlobStore in stead of BlobstoreUploadHandler. I created the following views (as per the render_change_form method) and updated urls.py:
def add_photo_feature(request):
def update_photo_feature(request):
This all works nicely but once I get into the view method I'm a bit lost. How do I get the Blob key from the request object so I can store it with PhotoFeature? I use standard Django, not Django non-rel. I found this related question but it appears not to contain a solution. I also inspected the request object which gets passed into the view but could not find anything relating to the blob key.
EDIT:
The Django request object contains a FILES dictionary which will give me an instance of InMemoryUploadedFile. I presume that somehow I should be able to retrieve the blob key from that...
EDIT 2:
Just to be clear: the uploaded photo appears in the Blobstore; that part works. It's just getting the key back from the Blobstore that's missing here.
EDIT 3:
As per Daniel's suggestion I added storage.py from the djangoappengine project which contains the suggested upload handler and added it to my SETTINGS.PY. This results in the following exception when trying to upload:
'BlobstoreFileUploadHandler' object has no attribute 'content_type_extra'
This is really tricky to fix. The best solution I have found is to use the file upload handler from the djangoappengine project (which is associated with django-nonrel, but does not depend on it). That should handle the required logic to put the blob key into request.FILES, as you'd expect in Django.
Edit
I'd forgotten that django-nonrel uses a patched version of Django, and one of the patches is here to add the content-type-extra field. You can replicate the functionality by subclassing the upload handler as follows:
from djangoappengine import storage
class BlobstoreFileUploadHandler(storage.BlobstoreFileUploadHandler):
"""Handler that adds blob key info to the file object."""
def new_file(self, field_name, *args, **kwargs):
# We need to re-process the POST data to get the blobkey info.
meta = self.request.META
meta['wsgi.input'].seek(0)
fields = cgi.FieldStorage(meta['wsgi.input'], environ=meta)
if field_name in fields:
current_field = fields[field_name]
self.content_type_extra = current_field.type_options
super(BlobstoreFileUploadHandler, self).new_file(field_name,
*args, **kwargs)
and reference this subclass in your settings.py rather than the original.

Best practice for Django sites to set up site configuration variables?

all! I am writing a Django blog site.
I am new to Django. Since Django has the philosophy of loose coupling, I believe it's best to follow their beliefs when using their framework.
So I am encountering a dilemma here:
I want to set up some variables for my blog, say, the blog title, slogan, and the maximum length of digest on the homepage of each blog I wrote, and how many blog digest should I display on the homepage per page.
I can do this by creating a new app in my Django project, and create models for my site's config variables, then read those variables from other app, but this practice obviously breaks the philosophy of loose coupling.
The only work around I can think of is setting up environment variables in my sites .wsgi file (I use Apache and mod_wsgi to serve Python scripts) But I don't think messing up with environment variable is 'clean' enough.
Can anyone suggest me a better solution?
First thing you can do is set up those variables in your project's settings module, many apps do that:
# settings
BLOG_TITLE = 'My title'
Then, a good practice is to provide settings defaults, so your app should have a settings file
# blog/settings.py
from django.conf import settings
BLOG_TITLE = getattr(settings, 'BLOG_TITLE', 'MY default title')
# Then wherever, views or context processor
from blog import settings # See how we're not importing project's settings
title = settings.BLOG_TITLE
Another alternative is to create a "Blog" model that contains all those variables, this may invite you to make your app to have a blog tied per Django sites
from django.contrib.sites.models import Site
class Blog(models.Model):
site = models.OneToOneField(Site) # Tied up to a Django site
title = models.CharField(max_length=256)
Now you can change those values from your Admin interface and use them in your views or context processor
site = Site.objects.get_current() # Installed Django Sites app and middleware
blog = site.blog
print blog.title
You can create settings or constants file in your app folder and use it. This way all your constants will be bound to your application:
apps/
blog/
__init__.py
models.py
urls.py
constants.py # <-- here it is!
File can look like this:
BLOG_TITLE = 'My super blog'
# ...
And you can use tour constants like this:
import blog.constants
# ...
return render_to_response('index.html', {title: blog.constants.BLOG_TITLE})
And in template:
<title>{{ title }}</title>
In my opinion, the best way to do this is by adding a model related to Site model using inheritance
First add site id to your Django settings file
SITE_ID = 1
now create a model in an app
from django.db import models
from django.contrib.sites.models import Site
class Settings(Site):
field_a = models.CharField(max_length=150, null=True)
field_b = models.CharField(max_length=150, null=True)
class Meta:
verbose_name_plural = 'settings'
db_table = 'core_settings' # core is name of my app
def __str__(self) -> str:
return 'Settings'
then edit apps.py file of that app
from django.apps import AppConfig
from django.db.models.signals import post_migrate
def build_settings(sender, **kwargs):
from django.contrib.sites.models import Site
from .models import Settings
if Settings.objects.count() < 1:
Settings.objects.create(site_ptr=Site.objects.first())
class CoreConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'project.apps.core'
def ready(self) -> None:
post_migrate.connect(build_settings, sender=self)
now every time you run migrations a row will auto-generated in core_settings that have a one to one relationship with your Site model
and now you can access to your settings like this
Site.objects.get_current().settings.access_id
optional: if have only a single site
unregister site model from admin site and disable creating and deleting settings model in admin panel
from django.contrib import admin
from . import models
from django.contrib.sites.models import Site
admin.site.unregister(Site)
#admin.register(models.Settings)
class SettingAdminModel(admin.ModelAdmin):
def has_delete_permission(self, request,obj=None) -> bool:
return False
def has_add_permission(self, request) -> bool:
return False