Custom Admin View and User Restriction - django-admin

I want to create a custom view in django admin that mirrors a change form from another model. I've got as far as creating a custom model admin class, and don't know where to go from here. I cant find any good examples for Django 1.8 on how to create a custom admin view.
Django Version: 1.8
class CustomerProductOrderAdmin(admin.ModelAdmin):
review_template = 'admin/onlineordering/order_template.html'
def get_urls(self):
urls = super(CustomerProductOrderAdmin, self).get_urls()
my_urls = patterns('',
(r'\d+/customer_template/$', self.admin_site.admin_view(self.customer_template)),
)
return my_urls + urls
def customer_template(self, request, id):
product_orders = CustomerProductOrder.objects.get(pk=id)
return render_to_response(self.review_template, {
'quantity': 'Quantity: %s' % product_orders.quantity,
}, context_instance=RequestContext(request))
I have a customer table that belong to this user table.
class Customer(models.Model):
customer = models.ForeignKey(settings.AUTH_USER_MODEL, limit_choices_to={'groups__name': "customers"})
/app/model/1 #pk = customer.id
The custom form will have this URL
/app/customform/
When the logged in user goes to /app/customform, they should not see the change form from /app/model/1. They should not see other users change forms. Also, I would like to limit access to the custom form, to a particular group of users. ie this group cannot see /app/model/ but can see /app/customform.

An example for how to add an independent template to admin page
At the model.py file inside the model class add a function
def version_summery(self, ):
batch_d= {}
fy = {}
for br in self.batchresult_set.all():
batch_d[br.name.strip()] = br.__dict__
fy['batch_d'] = batch_d.values()
x = render_to_string('admin/results/result_build_summary.html', fy)
return x
make sure the urls.py knows how to find the template 'result_build_summary.html'
and in the admin.py
readonly_fields = ( 'version_summery',)
fieldsets = (
('', {
'fields': ( 'version_summery', ),
}),
)

Related

Add multiple filters in Spree Commerce Rails

We need to implement custom filters for categories in spree ecommerce in latest version as seen here https://github.com/spree/spree .
We need to do it in a dynamic way because we have about 100 filters or more to make. The ideal solution would be to show all available filters in admin area and admin can activate/deactivate them for each category.
Current Scenario:
We know how to make a new filter and apply it. But it takes about four methods per filter as shown in the product_filter.rb file linked below.
Some links we have found useful:
https://gist.github.com/maxivak/cc73b88699c9c6b45a95
https://github.com/radar/spree-core/blob/master/lib/spree/product_filters.rb
Here is some code that allows you to filter by multiple properties. It is not ideal (no proper validation etc) but I guess it is better than doing multiple "in" subqueries.
def add_search_scopes(base_scope)
joins = nil
conditions = nil
product_property_alias = nil
i = 1
search.each do |name, scope_attribute|
scope_name = name.to_sym
# If method is defined in product_filters
if base_scope.respond_to?(:search_scopes) && base_scope.search_scopes.include?(scope_name.to_sym)
base_scope = base_scope.send(scope_name, *scope_attribute)
else
next if scope_attribute.first.empty?
# Find property by name
property_name = name.gsub('_any', '').gsub('selective_', '')
property = Spree::Property.find_by_name(property_name)
next unless property
# Table joins
joins = product if joins.nil?
product_property_alias = product_property.alias("filter_product_property_#{i}")
joins = joins.join(product_property_alias).on(product[:id].eq(product_property_alias[:product_id]))
i += 1
# Conditions
condition = product_property_alias[:property_id].eq(property.id)
.and(product_property_alias[:value].eq(scope_attribute))
conditions = conditions.nil? ? condition : conditions.and(condition)
end
end if search.is_a?(Hash)
joins ? base_scope.joins(joins.join_sources).where(conditions) : base_scope
end
def prepare(params)
super
#properties[:product] = Spree::Product.arel_table
#properties[:product_property] = Spree::ProductProperty.arel_table
end

ASP Classic for each in view page

I have Classic ASP application, within a class, I extract the record by a simple select.
In the view page (index.asp) I want to show the record, so I instantiated a class like:
Set user_profile = New user
Now I want manipulate and show records as I want:
<li><%=user.name%></li>
<li><%=user.surname%></li>
.......
In this case, logically, I have not a loop but I see only 1 record for instance.
Is it possible to add a for each in the view page like a real MVC system in ASP classic?
to clarify, i have this situation:
class category_view
Public id
Public name
Private Sub Class_Initialize()
sql = " SELECT * FROM category_tbl ORDER BY category_name ASC "
Set rs_cat = Server.CreateObject("ADODB.Recordset")
rs_cat.Open sql, Conn ,1,3
if rs_cat.RecordCount > 0 then
rs_rows = rs_cat.GetRows()
rs_catLoop = ubound(rs_rows,2)
For iCounter = 0 to rs_catLoop
id = rs_rows(0,iCounter)
name = rs_rows(1,iCounter)
Next
End if
rs_cat.close
End Sub
Private Sub Class_Terminate()
End Sub
end class
View page:
Set category = New category_view
(for each here)
<%=category.name%>
I need to access and reuse recordset information everywhere

Dynamically excluding fields in inline django admin

I want to exclude some fields in my inline based on my request user.
I know somehow I can handle this with methods like 'get_formsets', 'add_view', 'change_view', but I'm not sure what the syntax is.
Any suggestions?
I achieved what I needed with the next code in my inline class:
def get_formset(self, request, obj=None, **kwargs):
if request.user.groups.all().count() > 0:
if request.user.groups.all()[0].name == 'User Group Name':
kwargs['exclude'] = ['field_to_exclude',]
return super(MyInline, self).get_formset(request, obj, **kwargs)
The answer to this question gave me the hints: different fields for add and change pages in admin
There's also the get_exclude hook:
class FoodInline(TabularInline):
model = Food
def get_exclude(self, request, obj=None):
group = request.user.groups.first()
if group and group.name == 'User Group Name':
return ['field_to_exclude', ]
return self.exclude

getting Django current user on iOS app

I'm new to Django, I'm starting a Django app, I'm using the registration app and Django rest framework, this app will also serve as the backend for an iOS app, I already manage to create users from the iOS app and edit User Profiles from the browser, I need help to find an approach that lets the user edit his profile details once he is logged in. I tried setting a lookup_field like "user.username" to the UserProfileViewSet so I could access the UserProfile object and edit it, but that didn't work.
I also thought I could somehow return the user id after logging in and use this id to reference the userprofile I wanna edit but it does not seem practical at all. What do you think??
Other way I found to do this is by calling user.get_profile() but I don't know how I can make this work from the iOS app.
Here is my UserProfile Model, and serializers, any help would be great. Thanks
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True)
# Extra attribuets
pagetitle = models.TextField(null=False)
location = models.TextField(null=True)
website = models.TextField(null=True)
bio = models.TextField(null=True)
sex = models.TextField(null=True)
birthdate = models.DateField(null=True)
def __unicode__(self):
return "%s's profile" % self.user
def create_profile(sender, instance, created, **kwargs):
if created:
profile, created= UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_profile, sender=User)
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('username','email','password')
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer(many=False)
class Meta:
model = UserProfile
fields = ('user','bio')
I create the UserProfile using a signal like this
def create_profile(sender, instance, created, **kwargs):
if created:
profile, created= UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_profile, sender=User)
You didn't post your ViewSet code, so I have to guess. But your model should be set to User and your lookup_field should be set to username.
Something like:
class UserViewSet(ModelViewSet):
model = User
lookup_field = "username"
For everyone trying to get the profile for a user this is the way I managed to do it thanks to Kevin's help.
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
depth = 1
fields = ('id','username','email','profile')
class CurrentUserView(APIView):
def get(self, request):
serializer = UserSerializer(request.user)
return Response(serializer.data)
Using a url like this
url(r'^api/current-user',CurrentUserView.as_view(),
name="current_user"),
You will get an answer like this
"id": 1,
"username": "username",
"email": "email#email.com",
"profile": {
"id": 1,
"user": 1,
"bio": "My Bio",
"sex": "M",
"birthdate": "1987-12-02"
}

Grails: Refresh view after submit

I've seen various answers to similar questions, but not for this specific case:
I have a Grails gsp with several fields and a submit button. I want to enter a value in the first field, click submit, and have the controller return values into the remaining fields (including the original entry field). I want to do this with a simple page refresh (no AJAX) and it does not involve a database. I have it working fine with two gsp pages that are identical but have different names. I just call the first one, enter the value, and have the submit action point to the second. But I would like to be able to do it with a single gsp. A simplified version of my controller looks like this:
class CalculatorController {
def index = {
redirect(action: "input")
}
def input= {}
def calculateValues = {
def inputString = params.enterValue
def value2 = 'You entered something on the page'
[field1: inputString, field2: value2]
}
}
you need to have all of logic inside of the same closure if you want to use only one gsp. Test if the params are passed in and return the correct vals
Actually you don't need to have all of your logic in the same closure. Simply specify the view template to use in calculateValues...
def calculateValues = {
def inputString = params.enterValue
def value2 = 'You entered something on the page'
render(view: 'input', model: [field1: inputString, field2: value2])
}
By using the render method you can have multiple controller action reuse the same gsp view.

Resources