Ваш код, кажется, собирает уникальные значения по группам, превращаясь из высокой структуры данных в широкую структуру данных.
Один из самых ясных способов шага DATA - это использовать то, что мы называем циклом DOW, в котором SET находится внутри цикла. Этот пример кода предполагает не более 10 уникальных спутниковых значений на группу. (by
переменные можно рассматривать как ключевые переменные, а все остальные переменные будут спутники )
data have;
input user_id screen_id ;
datalines;
1 1
1 2
1 1
1 1
1 1
1 3
2 1
2 1
2 1
3 0
4 1
4 2
4 3
5 11
5 11
5 11
5 5
5 1
5 5
5 6
5 1
run;
data want;
_index = 0;
do until (last.user_id);
set have;
by user_id;
array ids screen_id1-screen_id10;
if screen_id not in ids then do;
_index + 1;
ids(_index) = screen_id;
end;
end;
drop _index screen_id;
run;
Одним из самых ясных процедурных способов является выбрать уникальные значения и транспонировать их.
proc sql;
create view uniqueScreenByUser as
select distinct user_id, screen_id
from have
order by user_id
;
proc transpose data=uniqueScreenByUser prefix=screen_id out=wantWide(drop=_name_);
by user_id;
var screen_id;
run;
Не уверен, что это все еще необходимо, но подумал, что поделюсь своим решением:
1) Установите django-tracking (спасибо за этот совет, Ван Гейл, Google Maps + GeoIP великолепен!)
2) Добавьте это промежуточное ПО:
from django.contrib.sessions.models import Session
from tracking.models import Visitor
from datetime import datetime
class UserRestrictMiddleware(object):
"""
Prevents more than one user logging in at once from two different IPs
"""
def process_request(self, request):
ip_address = request.META.get('REMOTE_ADDR','')
try:
last_login = request.user.last_login
except:
last_login = 0
if unicode(last_login)==unicode(datetime.now())[:19]:
previous_visitors = Visitor.objects.filter(user=request.user).exclude(ip_address=ip_address)
for visitor in previous_visitors:
Session.objects.filter(session_key=visitor.session_key).delete()
visitor.user = None
visitor.save()
3) Убедитесь, что оно идет после VisitorTrackingMiddleware, и вы обнаружите, что предыдущие логины автоматически удаляются, когда кто-то новый входит в систему :)
You'll need to do this with custom middleware.
In your middleware process_request()
method you will have access to the request object so you can do something like the following:
session_key = request.session.session_key
ip_address = request.META.get('REMOTE_ADDR', '')
Now you know the IP address, so check a model you create that (roughly) would look like this:
class SessionIPS(models.Model):
session = models.ForeignKey(Session)
IP = models.CharField(max_length=20)
So when a session is created or deleted you will modifiy your session ip's table accordingly, and when a request comes in make sure the IP address isn't being used for another session. If if is, then return a Http404 (or something like it) from the middleware.
A pluggable app that can show you a lot more detail (and even includes IP address in its own model) is django-tracking.
Промежуточное ПО Django , вероятно, поможет вам в этом. Проблема в том, что вы, вероятно, захотите разрешить несколько анонимных сеансов с одного и того же IP-адреса, даже сеансы с аутентификацией для разных пользователей, но не сеансы с аутентификацией для одного и того же пользователя.
Вы захотите:
Создать пользователя модель профиля для хранения IP-адреса последнего входа пользователя. См. Документацию Django Хранение дополнительной информации о пользователях .
Реализуйте серверную часть пользовательской аутентификации . Этот бэкэнд при запуске и успешной аутентификации пользователя (просто вызов super) стирает последний логин пользователя в модели профиля.
Реализуйте подкласс Django django.contrib.sessions.SessionMiddleware
, Реализуйте process_request
. Если модель профиля объекта request.user
не имеет IP-адреса, установите его и разрешите запрос. Если у него есть IP-адрес, и этот IP-адрес отличается от IP-адреса текущего запроса ( request.META.REMOTE_ADDR
), тогда сделайте все, что хотите, либо выйдите из системы другого пользователя, либо верните сообщение об ошибке отправителю запроса. .
Обновите файл settings.py
, чтобы сначала обрабатывался пользовательский бэкэнд аутентификации, а промежуточное ПО для пользовательского сеанса также обрабатывалось первым. Это включает в себя обновление настроек .AUTHENTICATION_BACKENDS
и settings.MIDDLEWARE_CLASSES
.